#pragma once #include "l4pcspak.h" #include "..\munga\notation.h" #include "..\munga\average.h" // These are purposely grouped as two parameters in one equate // (See PCSPAK.HH). // The standard PC COM ports ALWAYS use these combinations. //#define RIO_COM1 PCSP_COM1 //#define RIO_COM2 PCSP_COM2 //#define RIO_COM3 PCSP_COM3 //#define RIO_COM4 PCSP_COM4 class FilterChannel SIGNATURED { public: static const char *highName; static const char *centerName; static const char *lowName; static const char *joystickXName; static const char *joystickYName; static const char *throttleName; static const char *leftPedalName; static const char *rightPedalName; enum AlignMode { unaligned, normal }; enum PolarMode { unipolar, bipolar }; FilterChannel(); FilterChannel( NotationFile *init_file, const char *page_name, int default_min, int default_max ); FilterChannel( NotationFile *init_file, const char *page_name, int default_min, int default_center, int default_max ); ~FilterChannel(); void SetPolarity(PolarMode newPolarity); void SetDeadBand(Scalar amount_of_deadband); virtual void BeginAlignment(); virtual void EndAlignment(NotationFile *init_file=NULL); virtual Scalar Update(int value); Logical TestInstance() const; protected: void CalculateDeadBands(); const char *pageName; PolarMode polarity; AlignMode mode; int previousValue, min, max, center; int lowerRange, lowerDeadband; int upperRange, upperDeadband; Scalar deadbandScalar; Logical valuesFromFile; AverageOf average; }; class RIO; class Ranger SIGNATURED { friend class RIO; protected: Ranger( const char *page_name, int default_min, int default_max, Scalar deadband_scalar ); ~Ranger(); void ForceToZero(); void SetDeadBand(Scalar amount_of_deadband); Scalar Update(int input); Logical TestInstance() const; void Statistics(NotationFile *stat_file); const char *pageName; Logical sampledInputFlag; int offset, hardwareMinimum, hardwareMaximum, hardwareRange, deadbandInteger, highestInput, lowestInput; }; //########################################################################### // // RIOBase -- the abstract cockpit-controls surface (glass-cockpit step 2b). // // Splits the device-independent state + API out of the serial RIO so a // hardware-less device (PadRIO, built under BT_GLASS) can stand in behind // the same LBE4ControlsManager consumption sites (the manager holds a // RIOBase* -- L4CTRL.h). The serial RIO keeps its exact behavior; every // existing RIO::/RIO:: use resolves here through public // inheritance. Serial-flavored operations default to no-ops so a device // without the concept (no board check, no deadband hardware) needs no code. // //########################################################################### class RIOBase { public: enum RIOStatusType { BoardOk=0, BoardMissing=1, BoardBad=2, LampBad=3, RestartCount=4, AbandonCount=5, FullBufferCount=6 }; enum LampState{ solid=0, flashSlow=1, flashMed=2, flashFast=3, state1Off=0x00, state1Dim=0x04, state1Bright=0x0C, state2Off=0x00, state2Dim=0x10, state2Bright=0x30, }; enum RIOEventType { ButtonPressedEvent, ButtonReleasedEvent, KeyEvent, AnalogEvent, VersionEvent }; struct RIOKeyPair { int Unit; int Key; }; struct RIOEvent { RIOEventType Type; union { int Unit; RIOKeyPair Keyboard; }Data; }; RIOBase(); virtual ~RIOBase(); // // The operations every consumer needs a real implementation of. // virtual Logical GetNextEvent(RIOEvent *destinationPointer) = 0; virtual void SetLamp(int lampNumber, int state) = 0; // // Device liveness: True when the device is actually delivering input // (the serial RIO's `operational` flag). The game-side keyboard input // bridges stand down when an operational device exists (step 2c). // virtual Logical IsOperational() const = 0; // // Serial-flavored operations -- no-ops for devices without the concept. // virtual void ForceCenterJoystick() {} virtual void SetJoystickDeadBand(Scalar dead_band) {} virtual void SetThrottleDeadBand(Scalar dead_band) {} virtual void SetPedalsDeadBand(Scalar dead_band) {} virtual void RequestCheck() {} virtual void RequestVersion() {} virtual void RequestAnalogUpdate() {} virtual void GeneralReset() {} virtual void ResetThrottle() {} virtual void ResetLeftPedal() {} virtual void ResetRightPedal() {} virtual void ResetVerticalJoystick() {} virtual void ResetHorizontalJoystick() {} // // The shared control surface the manager's Execute() pushes from. // int TestModeActive; Scalar Throttle, LeftPedal, RightPedal, JoystickX, JoystickY; int MajorRevision, MinorRevision; }; class RIO : public PCSerialPacket, public RIOBase { protected: enum RIOCommand{ CheckRequest=0x80, VersionRequest, AnalogRequest, ResetRequest, LampRequest, CheckReply, VersionReply, AnalogReply, ButtonPressed, ButtonReleased, KeyPressed, KeyReleased, TestModeChange }; public: //Win32 Serial support: ADB 02/13/07 //RIO(Word port, Word intNum, Logical perform_tests = True); RIO(const char* port, Logical perform_tests = True); ~RIO(); Logical TestInstance() const; Logical GetNextEvent(RIOEvent *destinationPointer); Logical IsOperational() const { return operational; } void ForceCenterJoystick(), SetJoystickDeadBand(Scalar dead_band), SetThrottleDeadBand(Scalar dead_band), SetPedalsDeadBand(Scalar dead_band); void RequestCheck(), RequestVersion(), RequestAnalogUpdate(); void GeneralReset(), ResetThrottle(), ResetLeftPedal(), ResetRightPedal(), ResetVerticalJoystick(), ResetHorizontalJoystick(); void SetLamp(int lampNumber, int state); void TestCheckReply(int type, int location) { RIO::reply_check_string[1] = (Byte) (type & 0x7F); RIO::reply_check_string[2] = (Byte) (location & 0x7F); SendPacket((Byte *)reply_check_string); } void TestVersionReply(int major, int minor) { RIO::reply_version_string[1] = (Byte) (major & 0x7F); RIO::reply_version_string[2] = (Byte) (minor & 0x7F); SendPacket((Byte *)reply_version_string); } void TestAnalogReply() { SendPacket((Byte *)reply_analog_string); } void TestButtonPressed(int button) { RIO::reply_button_press_string[1] = (Byte) (button & 0x7F); SendPacket((Byte *)reply_button_press_string); } void TestButtonReleased(int button) { RIO::reply_button_release_string[1] = (Byte) (button & 0x7F); SendPacket((Byte *)reply_button_release_string); } void TestKeyPressed(int board, int key) { RIO::reply_key_press_string[1] = (Byte) (board & 0x7F); RIO::reply_key_press_string[2] = (Byte) (key & 0x7F); SendPacket((Byte *)reply_key_press_string); } void TestKeyReleased(int board, int key) { RIO::reply_key_release_string[1] = (Byte) (board & 0x7F); RIO::reply_key_release_string[2] = (Byte) (key & 0x7F); SendPacket((Byte *)reply_key_release_string); } void TestEnterTestMode() {SendPacket((Byte *)reply_test_enter_string);} void TestExitTestMode() {SendPacket((Byte *)reply_test_exit_string);} int ReceiveQueueCount() { return PCSerialPacket::ReceiveQueueCount(); } int TransmitQueueCount() { return PCSerialPacket::TransmitQueueCount(); } // (TestModeActive, the five analog Scalars, and Major/MinorRevision // moved to RIOBase -- the shared control surface.) int remoteRetryCount; int remoteAbandonCount; int remoteFullBufferCount; int lineErrorCount; int abandonCount; int overrunCount; int discardCount; // used by BeginAnalogCalibration() protected: void OpenFailureFile(); void CloseFailureFile(); void CheckErrors(); Logical operational; Ranger *leftPedalRanger, *rightPedalRanger; Ranger *throttleRanger; Ranger *joystickXRanger, *joystickYRanger; NotationFile *failureFile; int failureFileOpenCount; static Byte reply_check_string[]; static Byte reply_version_string[]; static Byte reply_analog_string[]; static Byte reply_button_press_string[]; static Byte reply_button_release_string[]; static Byte reply_key_press_string[]; static Byte reply_key_release_string[]; static Byte reply_test_enter_string[]; static Byte reply_test_exit_string[]; };