SpacePoint Fusion plugin 1.0

src/Plugin.cpp

00001 /*
00002 -----------------------------------------------------------------------------
00003 This source file is part of OpenSpace3D
00004 For the latest info, see http://www.openspace3d.com
00005 
00006 Copyright (c) 2010 I-maginer
00007 
00008 This program is free software; you can redistribute it and/or modify it under
00009 the terms of the GNU Lesser General Public License as published by the Free Software
00010 Foundation; either version 2 of the License, or (at your option) any later
00011 version.
00012 
00013 This program is distributed in the hope that it will be useful, but WITHOUT
00014 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00015 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
00016 
00017 You should have received a copy of the GNU Lesser General Public License along with
00018 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
00019 Place - Suite 330, Boston, MA 02111-1307, USA, or go to
00020 http://www.gnu.org/copyleft/lesser.txt
00021 
00022 You may alternatively use this source under the terms of a specific version of
00023 the OpenSpace3D Unrestricted License provided you have obtained such a license from
00024 I-maginer.
00025 -----------------------------------------------------------------------------
00026 */
00027 
00028 /*
00029  SpacePoint Fusion library based on USB HID library from WDK
00030  First version : april 2011
00031  Author : Aymeric Suteau
00032 */
00033 
00041 // Include Header File
00042 #include "Plugin.h"
00043 
00045 cbmachine ww;
00046 HWND HScol = NULL;      
00047 
00049 int OBJFUSIONSCOL;
00050 
00052 //===== CB Connected ===
00053 int SCOL_FUSION_CONNECTED_CB          = 0;
00054 int FUSION_CONNECTED_CB;
00055 
00056 //===== CB Disconnected ===
00057 int SCOL_FUSION_DISCONNECTED_CB       = 1;
00058 int FUSION_DISCONNECTED_CB;
00059 
00060 //===== CB New orientation data ===
00061 int SCOL_FUSION_ORIENTATION_DATA_CB   = 2;
00062 int FUSION_ORIENTATION_DATA_CB;
00063 
00064 //===== CB New raw data ===
00065 int SCOL_FUSION_RAW_DATA_CB           = 3;
00066 int FUSION_RAW_DATA_CB;
00067 
00068 //===== CB Button pressed/released ===
00069 int SCOL_FUSION_BUTTON_CB             = 4;
00070 int FUSION_BUTTON_CB;
00071 
00072 
00083 
00084 int destroyFusionObj(mmachine m, int handsys, int fusionTab) 
00085 {
00086         // Read the first element of a TAB element (table of objects)
00087         Fusion* FusionObj = (Fusion*) MMfetch(m, MTOP(fusionTab), 0);
00088 
00089         // Safely dispose of "FusionObj" pointer
00090         SAFE_DELETE(FusionObj);
00091 
00092         // Write the first element of a TAB element
00093         MMstore(m, MTOP(fusionTab), 0, 0);
00094 
00095         // Display debug message
00096         MMechostr(MSKDEBUG, "FusionObj destroyed.\n");
00097         return 0;
00098 }
00099 
00100 
00110 int _OpenFusionDevice(mmachine m) 
00111 {
00112         #ifdef  _SCOL_DEBUG_
00113                 MMechostr(MSKDEBUG,"_OpenFusionDevice\n");
00114         #endif
00115 
00116         // Declare local variables
00117         int k = 0;
00118         int dataType;
00119 
00120   // Test channel
00121   if (MMget(m, 1) == NIL)   // NOTE: Channel is the first parameter, so on the top of the stack
00122   {   
00123     MMechostr(MSKDEBUG,"_OpenFusionDevice : channel NIL\n");
00124     m->pp += 1;
00125     return 0;
00126   }
00127 
00128   // Retrieve data type (raw or orientation)
00129         if ((dataType = MTOI(MMpull(m))) == NIL)
00130                 dataType = ORIENTATION_DATA;  // Default data mode : orientation
00131 
00132         // Create Fusion instance
00133         Fusion * fusion = new Fusion();
00134   MMechostr(MSKDEBUG, "_OpenFusionDevice ...new SpacePoint Fusion instance created !\n");
00135 
00136         // Open Fusion device on USB port
00137   if (!fusion->OpenDevice(dataType)) 
00138   {
00139                 MMechostr(MSKDEBUG, "_OpenFusionDevice ...initialization failed\n");
00140                 SAFE_DELETE(fusion);
00141                 MMpull(m);                                                              // Pull the channel
00142                 MMpush(m, NIL);                                         // Push NIL on the stack
00143                 return 0;
00144         }
00145  
00146         // Allocate a block in the stack for a table of Fusion objects
00147         int fusionTab = MMmalloc(m, 1, TYPETAB);
00148         if (fusionTab == NIL) 
00149   {
00150                 MMechostr(MSKDEBUG, "_OpenFusionDevice ...MMmalloc failed\n");
00151                 SAFE_DELETE(fusion); 
00152                 MMpull(m);                                                              // Pull the channel
00153                 return MMpush(m, NIL);          // Push NIL on the stack
00154         }
00155         MMechostr(MSKDEBUG, "_OpenFusionDevice ...MMmalloc successful\n");
00156 
00157         // Push the TAB Fusion object into the stack
00158         MMstore(m, fusionTab, 0, (int)fusion);
00159         MMpush(m, PTOM(fusionTab));
00160 
00161         // Create a new SpacePoint Fusion object
00162         k = OBJcreate(m, OBJFUSIONSCOL, (int)fusion, NULL, NULL);
00163         MMechostr(MSKDEBUG, "_OpenFusionDevice ...object creation successful\n");
00164 
00165         #ifdef  _SCOL_DEBUG_
00166                 MMechostr(MSKDEBUG,"ok\n");
00167         #endif
00168 
00169         // Return Fusion object
00170         return k;
00171 }
00172 
00173 
00182 int _CloseFusionDevice(mmachine m) 
00183 {
00184         #ifdef  _SCOL_DEBUG_
00185                 MMechostr(MSKDEBUG,"_CloseFusionDevice\n");
00186   #endif
00187 
00188         // Get the table of Fusion objects into the stack (without pulling it)
00189         int fusionTab = MTOP(MMget(m, 0));
00190   MMechostr(MSKDEBUG, "_CloseFusionDevice\n");
00191         if (fusionTab == NIL)
00192   {
00193                 MMechostr(MSKDEBUG, "_CloseFusionDevice ...ObjFusion NIL\n");
00194                 MMset(m, 0, NIL);
00195                 return 0;
00196         }
00197 
00198         // Destroy Fusion object according to its type and magma object
00199   OBJdelTM(m, OBJFUSIONSCOL, PTOM(fusionTab));
00200 
00201         // Reinitialize the stack
00202         MMset(m, 0, ITOM(0));
00203 
00204         #ifdef  _SCOL_DEBUG_
00205                 MMechostr(MSKDEBUG,"ok\n");
00206         #endif
00207 
00208         return 0;
00209 }
00210 
00211 
00223 int _CBFusionConnected(mmachine m)
00224 {
00225         return OBJaddreflex(m, OBJFUSIONSCOL, SCOL_FUSION_CONNECTED_CB);
00226 }
00227 
00228 int getFusionConnectedCb(mmachine m, HWND h, unsigned msg, UINT id, LONG param, int *ret)
00229 {
00230         int k = 0;
00231         Fusion * FusionObj = (Fusion*) id;
00232         
00233         // OBJbeginreflex(mmachine, objecttype, objectptr, cbtype)
00234         if (OBJbeginreflex(m, OBJFUSIONSCOL, (int)FusionObj, SCOL_FUSION_CONNECTED_CB))
00235                 return 0;
00236 
00237         return (OBJcallreflex(m, 0));
00238 }
00239 
00240 
00252 int _CBFusionDisconnected(mmachine m)
00253 {
00254         return OBJaddreflex(m, OBJFUSIONSCOL, SCOL_FUSION_DISCONNECTED_CB);
00255 }
00256 
00257 int getFusionDisconnectedCb(mmachine m, HWND h, unsigned msg, UINT id, LONG param, int *ret)
00258 {
00259         int k = 0;
00260         Fusion * FusionObj = (Fusion*) id;
00261         
00262         // OBJbeginreflex(mmachine, objecttype, objectptr, cbtype)
00263         if (OBJbeginreflex(m, OBJFUSIONSCOL, (int)FusionObj, SCOL_FUSION_DISCONNECTED_CB))
00264                 return 0;
00265 
00266         return (OBJcallreflex(m, 0));
00267 }
00268 
00269 
00281 int _CBFusionOrientationData(mmachine m) 
00282 {
00283         // Add a reflex
00284         MMechostr(MSKDEBUG, "_CBFusionOrientationData ...adding reflex\n");
00285         return OBJaddreflex(m, OBJFUSIONSCOL, SCOL_FUSION_ORIENTATION_DATA_CB);
00286 }
00287 
00288 
00289 int getFusionOrientationDataCb(mmachine m, HWND h, unsigned msg, UINT id, LONG param, int *ret) 
00290 {
00291         int k = 0;
00292         float accX = 0, accY = 0, accZ = 0;                           // Initialize acceleration values
00293 
00294         // Cast id parameter to GloveObj type
00295         Fusion * FusionObj = (Fusion*) id;
00296   
00297         // Use : OBJbeginreflex(mmachine, type of object, ptr object, callback type)
00298         if (OBJbeginreflex(m, OBJFUSIONSCOL, (int)FusionObj, SCOL_FUSION_ORIENTATION_DATA_CB)) 
00299   {
00300                 //MMechostr(MSKDEBUG, "getFusionOrientationDataCb ...ObjFusion not found\n");
00301                 return 0;
00302         }
00303 
00304         // Retrieve acceleration values
00305   accX = FusionObj->fAcceleration[0];
00306   accY = FusionObj->fAcceleration[1];
00307   accZ = FusionObj->fAcceleration[2];
00308 
00309         // 1. Create tuple for acceleration values
00310         int tupleAcc = MMmalloc(m, 3, TYPETAB);
00311         if (tupleAcc == NIL) {
00312                 MMpush(m, NIL);         // Reinitialize the stack       
00313                 return MERRMEM;         // Return an error code (-1)
00314         }
00315         // Write TAB object field by field
00316         MMstore(m, tupleAcc, 0, FTOM(accX));
00317         MMstore(m, tupleAcc, 1, FTOM(accY));
00318   MMstore(m, tupleAcc, 2, FTOM(accZ));
00319 
00320         // Push tuple on the stack
00321   MMpush(m, PTOM(tupleAcc));
00322 
00323         // 2. Create tuple for quaternion values
00324         int tupleQuat = MMmalloc(m, 4, TYPETAB);
00325         if (tupleQuat == NIL) 
00326   {
00327                 MMpush(m, NIL);
00328                 return MERRMEM;
00329         }
00330         MMstore(m, tupleQuat, 0, FTOM(FusionObj->fQuaternion.x));
00331         MMstore(m, tupleQuat, 1, FTOM(FusionObj->fQuaternion.y));
00332   MMstore(m, tupleQuat, 2, FTOM(FusionObj->fQuaternion.z));
00333   MMstore(m, tupleQuat, 3, FTOM(FusionObj->fQuaternion.w));
00334   MMpush(m, PTOM(tupleQuat));
00335 
00336         // Call reflex previously defined (second parameter = number of user parameters)
00337         k = OBJcallreflex(m, 2);
00338         return k;
00339 }
00340 
00341 
00353 int _CBFusionRawData(mmachine m) 
00354 {
00355         // Add a reflex
00356         MMechostr(MSKDEBUG, "_CBFusionRawData ...adding reflex\n");
00357         return OBJaddreflex(m, OBJFUSIONSCOL, SCOL_FUSION_RAW_DATA_CB);
00358 }
00359 
00360 
00361 int getFusionRawDataCb(mmachine m, HWND h, unsigned msg, UINT id, LONG param, int *ret) 
00362 {
00363         int k = 0;
00364         int magX = 0, magY = 0, magZ = 0;
00365   int accX = 0, accY = 0, accZ = 0;
00366   int gyrR = 0, gyrP = 0, gyrY = 0;
00367   int res1 = 0, res2 = 0;
00368         int buttonL = 0, buttonR = 0;
00369 
00370         // Cast id parameter to GloveObj type
00371         Fusion * FusionObj = (Fusion*) id;
00372   
00373         // Use : OBJbeginreflex(mmachine, type of object, ptr object, callback type)
00374         if (OBJbeginreflex(m, OBJFUSIONSCOL, (int)FusionObj, SCOL_FUSION_RAW_DATA_CB)) 
00375   {
00376                 //MMechostr(MSKDEBUG, "getFusionRawDataCb ...ObjFusion not found\n");
00377                 return 0;
00378         }
00379 
00380   // Retrieve magnetometer values
00381   magX = FusionObj->iRawAxes[0];
00382   magY = FusionObj->iRawAxes[1];
00383   magZ = FusionObj->iRawAxes[2];
00384         
00385         // Retrieve accelerometer values
00386   accX = FusionObj->iRawAxes[3];
00387   accY = FusionObj->iRawAxes[4];
00388   accZ = FusionObj->iRawAxes[5];
00389 
00390   // Retrieve gyroscope values
00391   gyrR = FusionObj->iRawAxes[6];
00392   gyrP = FusionObj->iRawAxes[7];
00393   gyrY = FusionObj->iRawAxes[8];
00394 
00395   // Retrieve results 1 and 2 values
00396   res1 = FusionObj->iRawAxes[9];
00397   res2 = FusionObj->iRawAxes[10];
00398 
00399         // 1. Create tuple for magnetometer values
00400         int tupleMag = MMmalloc(m, 3, TYPETAB);
00401         if (tupleMag == NIL) 
00402   {
00403                 MMpush(m, NIL);         // Reinitialize the stack       
00404                 return MERRMEM;         // Return an error code (-1)
00405         }
00406         // Write TAB object field by field
00407   MMstore(m, tupleMag, 0, ITOM(magX));
00408         MMstore(m, tupleMag, 1, ITOM(magY));
00409   MMstore(m, tupleMag, 2, ITOM(magZ));
00410 
00411         // Push tuple on the stack
00412   MMpush(m, PTOM(tupleMag));
00413 
00414         // 2. Create tuple for accelerometer values
00415   int tupleAcc = MMmalloc(m, 3, TYPETAB);
00416         if (tupleAcc == NIL) 
00417   {
00418                 MMpush(m, NIL);         // Reinitialize the stack       
00419                 return MERRMEM;         // Return an error code (-1)
00420         }
00421   MMstore(m, tupleAcc, 0, ITOM(accX));
00422         MMstore(m, tupleAcc, 1, ITOM(accY));
00423   MMstore(m, tupleAcc, 2, ITOM(accZ));
00424   MMpush(m, PTOM(tupleAcc));
00425   
00426   // 3. Create tuple for gyroscope values
00427   int tupleGyr = MMmalloc(m, 3, TYPETAB);
00428         if (tupleGyr == NIL) 
00429   {
00430                 MMpush(m, NIL);         // Reinitialize the stack       
00431                 return MERRMEM;         // Return an error code (-1)
00432         }
00433   MMstore(m, tupleGyr, 0, ITOM(gyrR));
00434         MMstore(m, tupleGyr, 1, ITOM(gyrP));
00435   MMstore(m, tupleGyr, 2, ITOM(gyrY));
00436   MMpush(m, PTOM(tupleGyr));
00437 
00438   // 4. Create tuple for results 1 and 2 values
00439   int tupleRes = MMmalloc(m, 2, TYPETAB);
00440         if (tupleRes == NIL) 
00441   {
00442                 MMpush(m, NIL);         // Reinitialize the stack       
00443                 return MERRMEM;         // Return an error code (-1)
00444         }
00445   MMstore(m, tupleRes, 0, ITOM(res1));
00446   MMstore(m, tupleRes, 1, ITOM(res2));
00447   MMpush(m, PTOM(tupleRes));
00448 
00449         // Call reflex previously defined (second parameter = number of user parameters)
00450         k = OBJcallreflex(m, 4);
00451         return k;
00452 }
00453 
00454 
00466 int _CBFusionButton(mmachine m) 
00467 {
00468         // Add a reflex
00469         MMechostr(MSKDEBUG, "_CBFusionButton ...adding reflex\n");
00470         return OBJaddreflex(m, OBJFUSIONSCOL, SCOL_FUSION_BUTTON_CB);
00471 }
00472 
00473 
00474 int getFusionButtonCb(mmachine m, HWND h, unsigned msg, UINT id, LONG param, int *ret) 
00475 {
00476         int k = 0;
00477         int fusionButtons = 0;
00478 
00479         // Cast id parameter to GloveObj type
00480         Fusion * FusionObj = (Fusion*) id;
00481   
00482         // Use : OBJbeginreflex(mmachine, type of object, ptr object, callback type)
00483         if (OBJbeginreflex(m, OBJFUSIONSCOL, (int)FusionObj, SCOL_FUSION_BUTTON_CB)) 
00484   {
00485                 MMechostr(MSKDEBUG, "getFusionButtonCb ...ObjFusion not found\n");
00486                 return 0;
00487         }
00488 
00489   // Retrieve button values
00490   if (FusionObj->iButton[0])
00491     fusionButtons |= 1;
00492   if (FusionObj->iButton[1])
00493     fusionButtons |= 2;
00494 
00495   // Store Fusion buttons values into the stack
00496   MMpush(m, ITOM(fusionButtons));
00497 
00498         // Call reflex previously defined
00499         k = OBJcallreflex(m, 1);
00500         return k;
00501 }
00502 
00503 
00511 
00512 
00514 #define NbTplPKG 8
00515 
00516 
00520 char    *TplName[NbTplPKG] =
00521 {
00522         "ObjFusion",
00523   "_OpenFusionDevice",
00524         "_CloseFusionDevice",
00525   "_CBFusionConnected",
00526   "_CBFusionDisconnected",
00527   "_CBFusionOrientationData",
00528   "_CBFusionRawData",
00529   "_CBFusionButton"
00530 };
00531 
00532 
00536 int (*TplFunc[NbTplPKG])(mmachine m)=
00537 {
00538         NULL,                                                                                                                                                           // ObjFusion
00539   _OpenFusionDevice,                                                                                                    // _OpenFusionDevice
00540         _CloseFusionDevice,                                                                                                     // _CloseFusionDevice
00541   _CBFusionConnected,                         // _CBFusionConnected
00542   _CBFusionDisconnected,                      // _CBFusionDisconnected
00543   _CBFusionOrientationData,                   // _CBFusionOrientationData
00544   _CBFusionRawData,                           // _CBFusionRawData
00545   _CBFusionButton                             // _CBFusionButton
00546 };
00547 
00548 
00552 int TplNArg[NbTplPKG]=
00553 {
00554         TYPTYPE,                                                                                                                                                // ObjFusion
00555   2,                                                                                                                                                                    // _OpenFusionDevice
00556         1,                                                                                                                                                                      // _CloseFusionDevice
00557   3,                                          // _CBFusionConnected
00558   3,                                          // _CBFusionDisconnected
00559   3,                                          // _CBFusionOrientationData
00560   3,                                          // _CBFusionRawData
00561   3                                           // _CBFusionButton
00562 };
00563 
00564 
00568 char* TplType[NbTplPKG]=
00569 {
00570         NULL,                                                                                                                                                                                                     // ObjFusion
00571   "fun [Chn I] ObjFusion",                                                                                                                        // _OpenFusionDevice
00572         "fun [ObjFusion] I",                                                                                                                                // _CloseFusionDevice
00573   "fun [ObjFusion fun [ObjFusion u0] u1 u0] ObjFusion",                                     // _CBFusionConnected
00574   "fun [ObjFusion fun [ObjFusion u0] u1 u0] ObjFusion",                                     // _CBFusionDisconnected
00575   "fun [ObjFusion fun [ObjFusion u0 [F F F] [F F F F]] u1 u0] ObjFusion",                 // _CBFusionOrientationData
00576   "fun [ObjFusion fun [ObjFusion u0 [I I I] [I I I] [I I I] [I I]] u1 u0] ObjFusion",   // _CBFusionRawData
00577   "fun [ObjFusion fun [ObjFusion u0 I] u1 u0] ObjFusion"                                // _CBFusionButton
00578 };
00579 
00580 
00588 // Everything inside _cond and _endcond is ignored by doxygen
00590 
00595 int LoadFusion(mmachine m) 
00596 {
00597   // Return variable for PKhardpak function
00598         int k;
00599 
00600         // Declare a new type of object ("OBJFUSIONSCOL")
00601         OBJFUSIONSCOL = OBJregister(5, 1, destroyFusionObj, "OBJFUSIONSCOL");
00602 
00603   // Get new user events and associate these events with a callback
00604   FUSION_CONNECTED_CB = OBJgetUserEvent();
00605   OBJdefEvent(FUSION_CONNECTED_CB, (int (__cdecl *)(struct Mmachine *, int, unsigned int, int, int, int *))getFusionConnectedCb);
00606 
00607   FUSION_DISCONNECTED_CB = OBJgetUserEvent();
00608   OBJdefEvent(FUSION_DISCONNECTED_CB, (int (__cdecl *)(struct Mmachine *, int, unsigned int, int, int, int *))getFusionDisconnectedCb);
00609 
00610   FUSION_ORIENTATION_DATA_CB = OBJgetUserEvent();
00611         OBJdefEvent(FUSION_ORIENTATION_DATA_CB, (int (__cdecl *)(struct Mmachine *, int, unsigned int, int, int, int *))getFusionOrientationDataCb);
00612 
00613   FUSION_RAW_DATA_CB = OBJgetUserEvent();
00614         OBJdefEvent(FUSION_RAW_DATA_CB, (int (__cdecl *)(struct Mmachine *, int, unsigned int, int, int, int *))getFusionRawDataCb);
00615 
00616   FUSION_BUTTON_CB = OBJgetUserEvent();
00617         OBJdefEvent(FUSION_BUTTON_CB, (int (__cdecl *)(struct Mmachine *, int, unsigned int, int, int, int *))getFusionButtonCb);
00618 
00619         // Load package
00620         k = PKhardpak(m, "FusionEngine", NbTplPKG, TplName, TplFunc, TplNArg, TplType);
00621         return k;
00622 }
00624 
00625 
00630 extern "C" __declspec (dllexport) int SCOLloadFUSION(mmachine m, cbmachine w) 
00631 {
00632         SCOLinitplugin(w);
00633 
00634         // Get Scol window handle (for message callback)
00635         HScol = (HWND)SCgetExtra("hscol");
00636 
00637         // Display debug message
00638         MMechostr(MSKDEBUG, "SCOLloadFUSION loading SpacePoint Fusion DLL ...\n");
00639         
00640         LoadFusion(m);
00641         return 0;
00642 }
00643 
00644 
00649 extern "C" __declspec (dllexport) int SCOLfreeFUSION() 
00650 {
00651         // Display debug messages
00652         MMechostr(MSKDEBUG, "Release SpacePoint Fusion DLL\n");
00653         MMechostr(MSKDEBUG, "SpacePoint Fusion DLL CLOSED...\n\n" );
00654         return 0;
00655 }