L4RIO.h splits the abstract cockpit-control surface (RIOBase: enums, the five analog Scalars, GetNextEvent/SetLamp, no-op serial ops, NEW IsOperational) out of the serial RIO (RIO : PCSerialPacket, RIOBase -- byte-for-byte behavior kept, ctor assigns as before); LBE4ControlsManager holds a RIOBase* and gains the gated L4CONTROLS=PAD factory arm (BT_GLASS; OFF build logs+ignores the token). NEW gated TUs: L4PADRIO (XInput+keyboard synthesize the surface; 3s hot-plug re-probe; focus-guarded keys; per-poll AnalogEvent heartbeat; lampState[] + static SetScreenButton/GetLampState for the panel) and L4PADBINDINGS (content\bindings.txt profile, self-documenting default written on first run; deflect/slew/set axis model; addresses validated against ButtonCount). Verified live (glass build, L4CONTROLS=PAD): bindings written+parsed 44/10/5, XInput pad detected, 121 streamed mappings install via stock PrimaryRIO path, 2157 frames clean. Pod build (gates OFF) compiles the split with zero behavioral delta. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
398 lines
8.2 KiB
C++
398 lines
8.2 KiB
C++
#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<int> 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::<enum>/RIO::<member> 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[];
|
|
};
|