//////////////////////////////////////////////////////////////////////////////
//
// Asura_PS2_ControlPortDevice.h
//
// Created by Neil Massey.
//
// Copyright (c) 2002 Rebellion. All rights reserved.
//
// Declaration of a class that handles input from a control port device 
// (i.e. Dualshock, DS2, GCon1 etc.)
//
//////////////////////////////////////////////////////////////////////////////

// B E G I N   F I L E   W R A P P E R ///////////////////////////////////////

#ifdef ASURA_USE_PRAGMA_ONCE
    #pragma once
#endif

#ifndef ___ASURA_PS2_CONTROLPORTDEVICE_H___
#define ___ASURA_PS2_CONTROLPORTDEVICE_H___ 1

// Stdlib platform-specific.
#include <eetypes.h>

// Engine platform-specific.
#include "Input/Asura_PS2_Input.h"

// Enums for devices plugged into control port
enum DeviceTypeId {DT_NEGCON = 0x02,		// Requires calibration screen
				   DT_DIGITAL = 0x04, 
				   DT_ANALOG_JSTICK = 0x05,	// Requires calibration screen
				   DT_GUNCON = 0x06,		// Requires calibration screen
				   DT_DUALSHOCK = 0x07, 
				   DT_DUALSHOCK_PRESSURE = 0x79};

const int ASURA_PS2_VM_LARGE_MOTOR = 1;
const int ASURA_PS2_VM_SMALL_MOTOR = 0;

class Asura_PS2_ControlPortDevice
{
    friend class Asura_PS2_Input;
	public:
		Asura_PS2_ControlPortDevice(int iPort, int iSlot, bool bEnablePressure);
		~Asura_PS2_ControlPortDevice(void);

		void Update(void);
		void Translate(u_char *piAsuraInputBufferOffset, float *piAsuraAxis_BufferOffset);
		bool Available(void);
		int	 GetId(void);

		// Set calibration values :
		// for NegCon (DT_NEGCON) values are centre position, max twist
		// for GunCon (DT_GUNCON) values are x co-ord and y co-ord of centre point of screen
		// for analog joystick (DT_ANALOG_JSTICK) values are stick number, x centre, y centre, maximum throw
		// note : calibration is floating point and should be derived from the AsuraAxis buffer
		void SetCalibration(float fData1, float fData2);
		void SetCalibration(int iSide, float fData1, float fData2, float fData3);

		// Set rumble effect
        // (NRM - 07.04.2003) now takes amount for small motor in parameter 1, amount for large motor in parm 2
        // (NRM - 07.04.2003) only use once per frame - but you should be using Asura_Rumble_System anyway!
		void SetRumble(u_char ucAmountSmall, u_char ucAmountLarge);

		// This allocates the memory now!
		static u_long128* GetMemoryOfBuffer(int iPort, int iSlot);

	private:
		// Data used as a buffer when reading from pad
		static u_long128* s_uPadDmaBuffer[8];

		// Data returned when reading from the pad
		u_char acDataBuffer[32];
		bool m_bAvail;
		bool m_bReadyToTranslate;
		bool m_bEnablePressure;
		int  m_iPortNumber;
		int  m_iSlotNumber;
		int  m_iPhase;
		int	 m_iNextPhase;
		int  m_iCtrlId;
		int  m_iCtrlOldId;

		// For rumble
		int  m_iNActuators;
		u_char m_ucActDirect[6];
		u_char m_ucActAlign[6];

		// Calibration data
		float m_fCalibrationData[2][4];

		// Private translation functions - map ps2 input to Asura inputs
		void TranslateNegCon(u_char *piAsuraInputBufferOffset, float *piAsuraAxis_BufferOffset);
		void TranslateGunCon(u_char *piAsuraInputBufferOffset, float *piAsuraAxis_BufferOffset);
		void TranslateDigital(u_char *piAsuraInputBufferOffset, float *piAsuraAxis_BufferOffset);
		void TranslateAnalogJoyStick(u_char *piAsuraInputBufferOffset, float *piAsuraAxis_BufferOffset);
		void TranslateDualshock(u_char *piAsuraInputBufferOffset, float *piAsuraAxis_BufferOffset);

		float ConvertPS2AxisToAsuraAxis(u_char PS2Axis, float fDeadZone);
        void ProcessRumble(void);
		bool IsControllerSupported();
};

// E N D   F I L E   W R A P P E R ///////////////////////////////////////////

#endif // #ifndef ___ASURA_PS2_CONTROLPORTDEVICE_H___
