// joystick.cxx -- joystick support
//
// Written by Curtis Olson, started October 1998.
//
// Copyright (C) 1998  Curtis L. Olson - curt@me.umn.edu
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// $Id$
// (Log is kept at end of this file)


#ifdef HAVE_CONFIG_H
#  include <config.h>
#endif

#ifdef HAVE_WINDOWS_H
#  include <windows.h>                     
#endif

#include <Aircraft/aircraft.hxx>
#include <Debug/fg_debug.h>

#if defined( ENABLE_LINUX_JOYSTICK )
#  include <Joystick/js.hxx>
#elif defined( ENABLE_GLUT_JOYSTICK )
#  include <GL/glut.h>
#  include <XGL/xgl.h>
#endif


#include "joystick.hxx"


#if defined( ENABLE_LINUX_JOYSTICK )

    // joystick classes
    static jsJoystick *js0;
    static jsJoystick *js1;

    // these will hold the values of the axes
    static float *js_ax0, *js_ax1;

#elif defined( ENABLE_GLUT_JOYSTICK )

    // Joystick support using glut -- William Riley -- riley@technologist.com

    // Joystick fixed values for calibration and scaling
    static int joy_x_min=1000, /* joy_x_ctr=0, */ joy_x_max=-1000;
    static int joy_y_min=1000, /* joy_y_ctr=0, */ joy_y_max=-1000;
    static int joy_z_min=1000, /* joy_z_ctr=0, */ joy_z_max=-1000;
    static int joy_x_dead_min=100, joy_x_dead_max=-100;
    static int joy_y_dead_min=100, joy_y_dead_max=-100;
    static int joy_z_dead_min=100, joy_z_dead_max=-100;

#else
#  error port me: no joystick support
#endif



#if defined( ENABLE_GLUT_JOYSTICK )

// Function called by glutJoystickFunc(), adjusts read values and
// passes them to the necessary aircraft control functions
void joystick(unsigned int buttonMask, int js_x, int js_y, int js_z)
{
    double joy_x, joy_y, joy_z;
    // adjust the values to fgfs's scale and allow a 'dead zone' to
    // reduce jitter code adapted from joystick.c by Michele
    // F. America - nomimarketing@mail.telepac.pt
    if( js_x >= joy_x_dead_min && js_x <= joy_x_dead_max ) {
	joy_x = 0.0;
    } else {
	joy_x = (double)js_x/(double)(joy_x_max-joy_x_min);
    }	
    if( js_y >= joy_y_dead_min && js_y <= joy_y_dead_max ) {
	joy_y = 0.0;
    } else {
	joy_y = (double)js_y/(double)(joy_y_max-joy_y_min);
    }
    if( js_z >= joy_z_dead_min && js_z <= joy_z_dead_max ) {
	joy_z = 0.0;
    } else {
	joy_z = (double)js_z/(double)(joy_z_max-joy_z_min);
    }
    // Scale the values up for full range of motion
    joy_x *= 2.0;
    joy_y *= 2.0;
    joy_z = (((joy_z*2.0)+1.0)/2);
    // Pass the values to the control routines
    controls.set_elevator( joy_y );
    controls.set_aileron( -joy_x ); 
    controls.set_throttle( fgCONTROLS::FG_ALL_ENGINES, joy_z );
}

#endif // ENABLE_GLUT_JOYSTICK


// Initialize the joystick(s)
int fgJoystickInit( void ) {

    fgPrintf( FG_INPUT, FG_INFO, "Initializing joystick\n");

#if defined( ENABLE_LINUX_JOYSTICK )

    js0 = new jsJoystick ( 0 );
    js1 = new jsJoystick ( 1 );

    if ( js0->notWorking () ) {
	// not working
    } else {
	// allocate storage for axes values
	js_ax0 = new float [ js0->getNumAxes() ];

	// configure
	js0->setDeadBand( 0, 0.1 );
	js0->setDeadBand( 1, 0.1 );

	fgPrintf ( FG_INPUT, FG_INFO, 
		   "  Joystick 0 detected with %d axes\n",
		   js0->getNumAxes() );
    }

    if ( js1->notWorking () ) {
	// not working
    } else {
	// allocate storage for axes values
	js_ax1 = new float [ js1->getNumAxes() ];

	// configure
	js1->setDeadBand( 0, 0.1 );
	js1->setDeadBand( 1, 0.1 );

	fgPrintf ( FG_INPUT, FG_INFO,
		   "  Joystick 1 detected with %d axes\n",
		   js1->getNumAxes() );
    }

    if ( js0->notWorking() && js1->notWorking() ) {
	fgPrintf ( FG_INPUT, FG_INFO, "  No joysticks detected\n" );
	return 0;
    }

#elif defined( ENABLE_GLUT_JOYSTICK )

    glutJoystickFunc(joystick, 100);

#else
#  error port me: no joystick support
#endif

    return 1;
}


#if defined( ENABLE_LINUX_JOYSTICK )

// update the control parameters based on joystick intput
int fgJoystickRead( void ) {
    int b;

    if ( ! js0->notWorking() ) {
	js0->read( &b, js_ax0 ) ;
	controls.set_aileron( js_ax0[0] );
	controls.set_elevator( -js_ax0[1] );
    }

    if ( ! js1->notWorking() ) {
	js1->read( &b, js_ax1 ) ;
	controls.set_rudder( js_ax1[0] );
	controls.set_throttle( fgCONTROLS::FG_ALL_ENGINES, -js_ax1[1] * 1.05 );
    }

    return 1;
}

#endif // ENABLE_LINUX_JOYSTICK


// $Log$
// Revision 1.4  1998/10/27 02:14:32  curt
// Changes to support GLUT joystick routines as fall back.
//
// Revision 1.3  1998/10/25 14:08:44  curt
// Turned "struct fgCONTROLS" into a class, with inlined accessor functions.
//
// Revision 1.2  1998/10/25 10:56:25  curt
// Completely rewritten to use Steve Baker's joystick interface class.
//
// Revision 1.1  1998/10/24 22:28:16  curt
// Renamed joystick.[ch] to joystick.[ch]xx
// Added js.hxx which is Steve's joystick interface class.
//
// Revision 1.7  1998/04/25 22:06:29  curt
// Edited cvs log messages in source files ... bad bad bad!
//
// Revision 1.6  1998/04/18 04:14:05  curt
// Moved fg_debug.c to it's own library.
//
// Revision 1.5  1998/02/12 21:59:44  curt
// Incorporated code changes contributed by Charlie Hotchkiss
// <chotchkiss@namg.us.anritsu.com>
//
// Revision 1.4  1998/02/03 23:20:20  curt
// Lots of little tweaks to fix various consistency problems discovered by
// Solaris' CC.  Fixed a bug in fg_debug.c with how the fgPrintf() wrapper
// passed arguments along to the real printf().  Also incorporated HUD changes
// by Michele America.
//
// Revision 1.3  1998/01/27 00:47:54  curt
// Incorporated Paul Bleisch's <pbleisch@acm.org> new debug message
// system and commandline/config file processing code.
//
// Revision 1.2  1997/12/30 20:47:40  curt
// Integrated new event manager with subsystem initializations.
//
// Revision 1.1  1997/08/29 18:06:54  curt
// Initial revision.
//