Página principal | Jerarquía de la clase | Lista alfabética | Lista de componentes | Lista de archivos | Miembros de las clases | Archivos de los miembros | Páginas relacionadas

joystick.C

Ir a la documentación de este archivo.
00001 //===========================================================================
00002 //= joystick.cc                                           Noviembre de 1998 =
00003 //=-------------------------------------------------------------------------=
00004 //= Definiciones de las clase JOYSTICK*.                                    =
00005 //=-------------------------------------------------------------------------=
00006 //= ADVERTENCIA: ESTE SOFTWARE NO ESTA CONCEBIDO NI DISENNADO PARA EL USO   =
00007 //= EN EQUIPO DE CONTROL EN LINEA EN ENTORNOS PELIGROSOS QUE REQUIERAN UN   =
00008 //= DESEMPENNO LIBRE DE FALLAS, COMO LA OPERACION DE PLANTAS NUCLEARES,     = 
00009 //= SISTEMAS DE NAVEGACION O COMUNICACION EN AVIONES, TRAFICO AEREO,        =
00010 //= EQUIPO MEDICO DEL CUAL DEPENDAN VIDAS HUMANAS O SISTEMAS DE ARMAMENTO,  =
00011 //= EN LOS CUALES UNA FALLA EN EL SOFTWARE PUEDA IMPLICAR DIRECTAMENTE LA   =
00012 //= MUERTE, DANNOS PERSONALES O DANNOS FISICOS Y/O AMBIENTALES GRAVES       =
00013 //= ("ACTIVIDADES DE ALGO RIESGO").                                         =
00014 //=-------------------------------------------------------------------------=
00015 //= Autor original: Oscar J. Chavarro G.  A.K.A. JEDILINK. Copyright (c),   =
00016 //= 1997 - 2003, oscarchavarro@hotmail.com                                  =
00017 //= AQUYNZA es software libre, y se rige bajo los terminos de la licencia   =
00018 //= LGPL de GNU (http://www.gnu.org). Para mayor informacion respecto a la  =
00019 //= licencia de uso, consulte el archivo ./doc/LICENCIA en la distribucion. =
00020 //===========================================================================
00021 
00022 #include "toolkits/media/joystick.h"
00023 
00024 #if PLATAFORMA == i386_WIN32_VC
00025     #include <dinput.h>
00026     #include <assert.h>
00027     #include <malloc.h>
00028 #endif
00029 
00030 #include <string.h>
00031 #include <stdlib.h>
00032 
00033 //===========================================================================
00034 //= Operaciones especificas de i386_WIN32_VC                                     =
00035 //===========================================================================
00036 
00037 #if PLATAFORMA == i386_WIN32_VC
00038 
00039 static LONG WINAPI
00040 receptor_eventos_nulo(HWND w, UINT tipo_mensaje, UINT uParam, LONG lParam)
00043 {
00044     return DefWindowProc(w, tipo_mensaje, uParam, lParam);
00045 }
00046 
00047 static HWND
00048 crear_ventana_joystick(void)
00049 {
00050     static int lista = 0;
00051     static HWND receptora = NULL;
00052 
00053     if ( lista ) return receptora;
00054 
00055     //- CREE LA CLASE DE VENTANA RECEPTORA DE EVENTOS ------------
00056     // OJO: Jugar con lo siguiente en el STYLE: CS_BYTEALIGNCLIENT,
00057     // CS_BYTEALIGNWINDOW, CS_DBLCLKS, CS_NOCLOSE
00058     WNDCLASS atributos_de_ventana = {
00059         CS_GLOBALCLASS,     // UINT    style; 
00060         (WNDPROC)receptor_eventos_nulo,  // WNDPROC lpfnWndProc; 
00061         0,                  // int     cbClsExtra; 
00062         0,                  // int     cbWndExtra; 
00063         0,                  // HANDLE  hInstance; 
00064         NULL,               //HICON   hIcon; 
00065         NULL,               //HCURSOR hCursor; 
00066         NULL,               //HBRUSH  hbrBackground; 
00067         "",                 // Sin menu por defecto.
00068         "AQUYNZA_JOYSTICK_event_handler"    // LPCTSTR lpszClassName; 
00069     };
00070 
00071     if ( !RegisterClass(&atributos_de_ventana) ) {
00072         fprintf(stderr, "ERROR: No puedo crear la clase!\n");
00073         fflush(stdout);
00074         return NULL;
00075     }
00076 
00077     //- CREE LA VENTANA RECEPTORA ------------------------------
00078     receptora = CreateWindowEx( 
00079         WS_EX_NOPARENTNOTIFY | WS_EX_TRANSPARENT,
00080             // OJO: Revisar los "extended windows styles"
00081         "AQUYNZA_JOYSTICK_event_handler", // Nombre de la clase de ventana
00082         "AQUYNZA JOYSTICK event handler",  // Nombre de la ventana
00083         WS_ICONIC  | // Estilo de borde
00084         WS_CAPTION | WS_MINIMIZEBOX |WS_MAXIMIZEBOX | // Estilo de barra
00085         WS_CLIPSIBLINGS | WS_CLIPCHILDREN,  // Siempre activos!
00086         0, 0, 10, 10,  // Geometria de la ventana
00087         NULL, // Ventana padre: en este caso es la root-window
00088         NULL, // handle to menu (en este caso sin menu por defecto)
00089         0, // handle to application instance (ver parametro)
00090         (LPVOID)NULL // Apuntador a datos de mi aplicacion
00091     );
00092 
00093     if ( !receptora ) {
00094         fprintf(stderr,
00095             "ERROR: No pudo crearse la ventana receptora de eventos!\n");
00096         fflush(stderr);
00097     }
00098 
00099     lista = 1;
00100     ShowWindow(receptora, SW_SHOWDEFAULT);  // OJO: Esto no deberia ir!
00101         return receptora;
00102 }
00103 
00104 #endif
00105 
00106 //===========================================================================
00107 //= Clase JOYSTICK                                                          =
00108 //===========================================================================
00109 
00110 #ifndef JOYSTICK_ENABLED
00111 JOYSTICK::JOYSTICK(char *)
00112 {
00113     fprintf(stderr, "<JOYSTICK> - ERROR: No soportado en esta plataforma!\n");
00114     exit(-1);
00115 }
00116 
00117 JOYSTICK::~JOYSTICK()
00118 {
00119     ;
00120 }
00121 
00122 BOOLEAN
00123 JOYSTICK::abrir(void)
00124 {
00125     return FALSE;
00126 }
00127 
00128 void
00129 JOYSTICK::cerrar(void)
00130 {
00131     ;
00132 }
00133 
00134 void
00135 JOYSTICK::consultar(double *, double *, int *)
00136 {
00137     ;
00138 }
00139 
00140 void
00141 JOYSTICK::calibrar(void)
00142 {
00143     ;
00144 }
00145 
00146 void
00147 JOYSTICK::actualizar(void)
00148 {
00149     ;
00150 }
00151 
00152 BOOLEAN
00153 JOYSTICK::consultar_variable(const char *, int &, void **)
00154 {
00155     return FALSE;
00156 }
00157 
00158 #endif
00159 
00160 #ifdef JOYSTICK_ENABLED
00161 
00162 JOYSTICK::JOYSTICK(
00163 #ifdef UNIX_ENABLED
00164     char *filename
00165 #endif
00166 #if PLATAFORMA == i386_WIN32_VC
00167     char * /*filename*/
00168 #endif
00169 )
00170 {
00171   #if PLATAFORMA == i386_LINUX_GCC || PLATAFORMA == SPARC64_LINUX_GCC
00172     archivo = filename;
00173     fd = -1;
00174   #endif
00175 
00176   #if PLATAFORMA == i386_WIN32_VC
00177     fd_device                             = NULL;
00178     direct_input_object                                 = NULL;
00179     gui_valido                           = FALSE;
00180   #endif
00181 
00182     fx = fy = 0;
00183 }
00184 
00185 JOYSTICK::~JOYSTICK()
00186 {
00187     cerrar();
00188 }
00189 
00190 
00191 BOOLEAN
00192 JOYSTICK::abrir(void)
00193 {
00194   #if PLATAFORMA == i386_LINUX_GCC || PLATAFORMA == SPARC64_LINUX_GCC
00195     fd = open (archivo, O_RDONLY);
00196     if ( fd < 0 ) {
00197         fprintf(stderr, "<JOYSTICK> ERROR - Joystick no encontrado.\n");
00198         fflush(stderr);
00199         return FALSE;
00200     }
00201   #endif
00202 
00203 #ifndef CBUILDER
00204 #if PLATAFORMA == i386_WIN32_VC
00205   HWND hwndApp = crear_ventana_joystick();
00206   HRESULT hResult;
00207   cerrar();       // Make sure the device is in an uninitialized state
00208 
00209   // create the DirectInput object
00210   hResult = DirectInputCreate(i386_WIN32_VC_instancia_actual, DIRECTINPUT_VERSION, &direct_input_object, NULL);
00211   if (FAILED(hResult)) 
00212     return FALSE;
00213 
00214   // Use the DirectInput object to try to find an attached joystick. First we
00215   // restrict our search to force-feedback joysticks.
00216   hResult = direct_input_object->EnumDevices( 
00217                                DIDEVTYPE_JOYSTICK, 
00218                                (LPDIENUMDEVICESCALLBACK)device_callback, 
00219                                this, 
00220                                DIEDFL_ATTACHEDONLY | DIEDFL_FORCEFEEDBACK 
00221                                );
00222   if (FAILED(hResult))
00223     return FALSE;
00224 
00225   if (!gui_valido) {
00226     // Since we didn't get a force-feedback joystick, try to get any attached joystick
00227     hResult = direct_input_object->EnumDevices( 
00228                                  DIDEVTYPE_JOYSTICK, 
00229                                  (LPDIENUMDEVICESCALLBACK)device_callback, 
00230                                  this, 
00231                                  DIEDFL_ATTACHEDONLY 
00232                                  );
00233 
00234     if (FAILED(hResult))        
00235       return FALSE;
00236   }
00237 
00238   // If no joystick was found, we better abort
00239   if (!gui_valido) 
00240     return FALSE;
00241 
00242   LPDIRECTINPUTDEVICE lpDIDevice = NULL;
00243 
00244   // Create the device
00245   hResult = direct_input_object->CreateDevice(guid, &lpDIDevice, NULL);
00246   if (FAILED(hResult)) {
00247     fd_device = NULL;
00248     return FALSE;
00249   }
00250 
00251   // Get the device2 interface
00252   hResult = lpDIDevice->QueryInterface(IID_IDirectInputDevice2, (LPVOID *)&fd_device);
00253   if (FAILED(hResult)) 
00254     return FALSE;
00255 
00256   // Set the data format of the device to be a joystick.
00257   hResult = fd_device->SetDataFormat(&c_dfDIJoystick);
00258   if (FAILED(hResult)) 
00259     return FALSE;
00260 
00261   hResult = fd_device->SetCooperativeLevel(
00262                                            hwndApp,
00263                                            DISCL_EXCLUSIVE | DISCL_BACKGROUND);
00264   if (FAILED(hResult))
00265     return FALSE;
00266 
00267   // acquire the device
00268   hResult = fd_device->Acquire();
00269   if (FAILED(hResult)){
00270     fd_device->Release();
00271     direct_input_object->Release();
00272     return FALSE;
00273   }
00274 
00275   //-----------------------------------------------------------------------
00276   DIDEVICEINSTANCE didi;      
00277   didi.dwSize = sizeof DIDEVICEINSTANCE; 
00278   fd_device->GetDeviceInfo(&didi);
00279   //OutputString(didi.tszProductName);
00280   printf("%s encontrado!\n", didi.tszProductName); fflush(stdout);
00281   set_gain(50 /*START_GAIN*/);
00282 
00283   // colocar el rangoX
00284   DIPROPRANGE diprg;
00285   diprg.diph.dwSize       = sizeof(diprg);
00286   diprg.diph.dwHeaderSize = sizeof(diprg.diph); 
00287   diprg.diph.dwObj        = DIJOFS_X; 
00288   diprg.diph.dwHow        = DIPH_BYOFFSET; 
00289   diprg.lMin              = -1000; 
00290   diprg.lMax              = +1000; 
00291  
00292   fd_device->SetProperty(DIPROP_RANGE, &diprg.diph); 
00293 
00294   // colocar el rangoY
00295   diprg.diph.dwSize       = sizeof(diprg); 
00296   diprg.diph.dwHeaderSize = sizeof(diprg.diph); 
00297   diprg.diph.dwObj        = DIJOFS_Y; 
00298   diprg.diph.dwHow        = DIPH_BYOFFSET; 
00299   diprg.lMin              = -1000; 
00300   diprg.lMax              = +1000; 
00301 
00302   fd_device->SetProperty(DIPROP_RANGE, &diprg.diph); 
00303 
00304 #endif // i386_WIN32_VC
00305 
00306 #endif // CBUILDER
00307 
00308     return TRUE;
00309 }
00310 
00311 void
00312 JOYSTICK::cerrar(void)
00313 {
00314   #if PLATAFORMA == i386_LINUX_GCC || PLATAFORMA == SPARC64_LINUX_GCC
00315     close(fd);
00316   #endif
00317 
00318   #if PLATAFORMA == i386_WIN32_VC
00319     if (fd_device != NULL) {
00320         fd_device->Unacquire();
00321         fd_device->Release();
00322         fd_device = NULL;
00323     }
00324     if (direct_input_object != NULL) {
00325         direct_input_object->Release();
00326         direct_input_object = NULL;
00327     }
00328   #endif
00329 }
00330 
00331 void
00332 JOYSTICK::consultar(double *x, double *y, int *botones)
00333 {
00334     actualizar();
00335     (*x) = fx;
00336     (*y) = fy;
00337     (*botones) = fbotones;
00338 }
00339 
00340 void
00341 JOYSTICK::actualizar(void)
00342 {
00343   #if PLATAFORMA == i386_LINUX_GCC || PLATAFORMA == SPARC64_LINUX_GCC
00344     if ( fd < 0 ) return;
00345 
00346     status = read(fd, &lowlevel_data, JS_RETURN);
00347     if ( status != JS_RETURN ) {
00348         fprintf(stderr, "<JOYSTICK> ERROR leyendo datos.\n");
00349         fflush(stderr);
00350         exit(-1);
00351     }
00352 
00353     fx = (((double)(lowlevel_data.x-64))/128) - 0.5;
00354     fy = 0.5 - (((double)(lowlevel_data.y-64))/128);
00355     fbotones = lowlevel_data.buttons;
00356   #endif
00357 
00358   #if PLATAFORMA == i386_WIN32_VC
00359     fx = 0;
00360     fy = 0;
00361     fbotones = 0x0;
00362 
00363     HRESULT     hr ;
00364     DIJOYSTATE  diJoyState ;
00365 
00366     // No device object?  Give up.
00367     if( !fd_device ) return;
00368 
00369     // Poll, or retrieve information from the device
00370     hr = fd_device->Poll() ;
00371     if( hr== DIERR_INPUTLOST || hr== DIERR_NOTACQUIRED ) {
00372         // If the poll failed, maybe we should acquire
00373         fd_device->Acquire() ;
00374 
00375         // Lets try the poll again
00376         hr = fd_device->Poll() ;
00377     }
00378     if( FAILED(hr) ) return;
00379 
00380     // Get the device state, and populate the DIJOYSTATE structure
00381     if( FAILED(fd_device->GetDeviceState( sizeof(DIJOYSTATE), 
00382                                           & diJoyState)) ) {
00383         return;
00384     }
00385 
00386     int i;
00387     fbotones = 0x0;
00388     for ( i = 0; i < 8; i++ ) {
00389         if ( diJoyState.rgbButtons[i] ) {
00390             fbotones |= (0x01 << i);
00391         }
00392     }
00393     fx = (double)diJoyState.lX / 1000;
00394     fy = (double)diJoyState.lY / 1000;
00395     fy *= -1;
00396   #endif
00397 }
00398 
00399 static double TMP_double;
00400 
00401 BOOLEAN
00402 JOYSTICK::consultar_variable(const char *nombre_variable, int &tipo, void **ref)
00403 {
00404     tipo = T_FLOAT;
00405     if ( strcmp(nombre_variable, "x") == 0 ) {
00406         TMP_double = fx;
00407         (*ref) = &TMP_double;
00408       }
00409       else if ( strcmp(nombre_variable, "y") == 0 ) {
00410         TMP_double = fy;
00411         (*ref) = &TMP_double;
00412       }
00413       else if ( strcmp(nombre_variable, "x1") == 0 ) {
00414         //printf("Reporto x1 = %.2f (%d)\n", fx, fbotones);  fflush(stdout);
00415         if ( !fbotones ) TMP_double = fx; else TMP_double = 0;
00416         (*ref) = &TMP_double;
00417       }
00418       else if ( strcmp(nombre_variable, "y1") == 0 ) {
00419         //printf("Reporto y1 = %.2f (%d)\n", fy, fbotones);  fflush(stdout);
00420         if ( !fbotones ) TMP_double = fy; else TMP_double = 0;
00421         (*ref) = &TMP_double;
00422       }
00423       else if ( strcmp(nombre_variable, "x2") == 0 ) {
00424         //printf("Reporto x2 = %.2f (%d)\n", fx, fbotones);  fflush(stdout);
00425         if ( fbotones == 0x01 ) TMP_double = fx; else TMP_double = 0;
00426         (*ref) = &TMP_double;
00427       }
00428       else if ( strcmp(nombre_variable, "y2") == 0 ) {
00429         //printf("Reporto y2 = %.2f (%d)\n", fy, fbotones);  fflush(stdout);
00430         if ( fbotones == 0x01 ) TMP_double = fy; else TMP_double = 0;
00431         (*ref) = &TMP_double;
00432       }
00433       else if ( strcmp(nombre_variable, "x3") == 0 ) {
00434         //printf("Reporto x3 = %.2f (%d)\n", fx, fbotones);  fflush(stdout);
00435         if ( fbotones == 0x02 ) TMP_double = fx; else TMP_double = 0;
00436         (*ref) = &TMP_double;
00437       }
00438       else if ( strcmp(nombre_variable, "y3") == 0 ) {
00439         //printf("Reporto y3 = %.2f (%d)\n", fy, fbotones);  fflush(stdout);
00440         if ( fbotones == 0x02 ) TMP_double = fy; else TMP_double = 0;
00441         (*ref) = &TMP_double;
00442       }
00443       else if ( strcmp(nombre_variable, "x4") == 0 ) {
00444         //printf("Reporto x4 = %.2f (%d)\n", fx, fbotones);  fflush(stdout);
00445         if ( fbotones == 0x03 ) TMP_double = fx; else TMP_double = 0;
00446         (*ref) = &TMP_double;
00447       }
00448       else if ( strcmp(nombre_variable, "y4") == 0 ) {
00449         //printf("Reporto y4 = %.2f (%d)\n", fy, fbotones);  fflush(stdout);
00450         if ( fbotones == 0x03 ) TMP_double = fy; else TMP_double = 0;
00451         (*ref) = &TMP_double;
00452       }
00453       else {
00454         return FALSE;
00455       }
00456     ;
00457     return TRUE;
00458 }
00459 
00460 #define CHECK() if (status == -1) {  perror ("jscal"); exit (1);  }
00461 
00462 void
00463 JOYSTICK::calibrar(void)
00464 {
00465   #if PLATAFORMA == i386_LINUX_GCC || PLATAFORMA == SPARC64_LINUX_GCC
00466     int tmp;
00467     long tmpl;
00468 
00469     printf (
00470       "Mueva el joystick a la esquina superior izquierda y oprima un boton\n");
00471     while ( (read (fd, &lowlevel_data, JS_RETURN) > 0) && 
00472             lowlevel_data.buttons == 0x00 );
00473     while ( (read (fd, &lowlevel_data, JS_RETURN) > 0) && 
00474             lowlevel_data.buttons != 0x00 );
00475 
00476     status = ioctl(fd, JS_GET_TIMEOUT, &tmp);                 CHECK();
00477     //printf ("Timeout value = %d\n", tmp);
00478 
00479     status = ioctl(fd, JS_GET_TIMELIMIT, &tmpl);              CHECK();
00480     //printf ("Timelimit value = %ld ms\n", tmpl);
00481 
00482     //printf("Setting Timelimit = 10 ms\n");
00483     tmpl = 10;
00484     status = ioctl (fd, JS_SET_TIMELIMIT, &tmpl);             CHECK();
00485 
00486     status = ioctl (fd, JS_GET_CAL, &lowlevel_data);          CHECK();
00487   //printf ("Current correction: %d , %d\n", lowlevel_data.x, lowlevel_data.y);
00488 
00489     printf (
00490         "Mueva el joystick a la esquina inferior derecha y oprima un boton\n");
00491     while ( (read (fd, &lowlevel_data, JS_RETURN) > 0) && 
00492             lowlevel_data.buttons == 0x00 );
00493 
00494     for ( tmp = 0; lowlevel_data.x > 0xff;
00495           tmp++, lowlevel_data.x = lowlevel_data.x >> 1 );
00496     lowlevel_data.x = tmp;
00497     for ( tmp = 0; lowlevel_data.y > 0xff;
00498           tmp++, lowlevel_data.y = lowlevel_data.y >> 1 );
00499     lowlevel_data.y = tmp;
00500 
00501   //printf ("Setting correction: %d , %d\n", lowlevel_data.x, lowlevel_data.y);
00502     status = ioctl (fd, JS_SET_CAL, &lowlevel_data);          CHECK();
00503 
00504     status = ioctl (fd, JS_GET_CAL, &lowlevel_data);          CHECK();
00505   //printf ("Verify Correction (interrupt to exit): %d, %d\n",
00506   //        lowlevel_data.x,  lowlevel_data.y);
00507 
00508     printf("<JOYSTICK>: Calibracion terminada con exito.\n");
00509     fflush(stdout);
00510   #endif
00511 }
00512 
00513 #if PLATAFORMA == i386_WIN32_VC
00514 
00515 BOOLEAN
00516 JOYSTICK::set_gain(int gain)
00517 {
00518   if ( ! direct_input_object  ||  ! fd_device )
00519     return FALSE;
00520 
00521   if ( (gain < 0) || (gain > 100) )
00522     return FALSE;
00523 
00524   // set the ForceFeedback gain
00525   DIPROPDWORD   propGain;
00526   propGain.diph.dwSize          = sizeof propGain;
00527   propGain.diph.dwHeaderSize    = sizeof propGain.diph;
00528   propGain.diph.dwHow                   = DIPH_DEVICE;
00529   propGain.diph.dwObj                   = 0;
00530   propGain.dwData                               = 100 * gain;
00531 
00532   HRESULT hRes = fd_device->SetProperty(DIPROP_FFGAIN, &propGain.diph);
00533   if (FAILED(hRes))
00534     return FALSE;
00535 
00536   return TRUE;
00537 }
00538 
00539 #ifndef CBUILDER
00540 BOOLEAN
00541 JOYSTICK::device_callback(LPDIDEVICEINSTANCE pdidi, LPVOID pv)
00542 {
00543   // Return the first joystick we find. Our caller will restrict the
00544   // enumeration to force-feedback joysticks when appropriate.
00545   //
00546   // As a future enhancement, we could make a list of all joysticks
00547   // found and let the user choose which one to use.
00548   ((JOYSTICK *)pv)->guid = pdidi->guidInstance;
00549   ((JOYSTICK *)pv)->gui_valido = TRUE;
00550 
00551   return DIENUM_STOP;
00552 }
00553 #endif
00554 
00555 #endif // i386_WIN32_VC
00556 
00557 #endif // JOYSTICK_ENABLED
00558 
00559 //===========================================================================
00560 //= EOF                                                                     =
00561 //===========================================================================
00562 

Este archivo HTML ha sido generado automáticamente a partir del código fuente AQUYNZA. NO LO EDITE. Para mayor información contacte al autor.