Skip to content

psyqo Multi-tap driver and example update #1815

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 23 commits into from
Feb 27, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
6ce813b
Add getters for adc+pad type, update multitap example
johnbaumann Dec 13, 2024
de152b9
Fix(?) adc numbering, adc styling
johnbaumann Dec 13, 2024
07b6a96
Add getter for raw halfword. Fix+tidy example
johnbaumann Dec 21, 2024
0631089
Merge branch 'grumpycoders:main' into psyqo_multitap_additions
johnbaumann Dec 31, 2024
929e76f
Bump copyright, use vprintf, play with some logic
johnbaumann Jan 8, 2025
e73f7fd
Address some of the wascally wabbit's nitpicks
johnbaumann Jan 8, 2025
7b4f815
Merge branch 'main' into psyqo_multitap_additions
johnbaumann Jan 8, 2025
af630c4
Fix documenation mistake, woops.
johnbaumann Jan 8, 2025
f3ee66e
Change Pad to enum class, add casts, more doc
johnbaumann Jan 9, 2025
131796e
Kill other adc getters, too redundant.
johnbaumann Jan 9, 2025
2e21c2f
Sneaking in more changes... Try to improve code readability
johnbaumann Jan 10, 2025
3215462
The rabbit is right... ugh
johnbaumann Jan 10, 2025
ceea701
Merge branch 'main' into psyqo_multitap_additions
johnbaumann Jan 10, 2025
a1a2ae7
Add fishingcon, more adc, resize PadData
johnbaumann Jan 23, 2025
3b85d77
Fix for analog pad with LED previously config'd off, bad pad ID
johnbaumann Feb 16, 2025
791b520
Merge branch 'main' into psyqo_multitap_additions
johnbaumann Feb 16, 2025
98aa616
Rename and add some documentation, small tweaks
johnbaumann Feb 20, 2025
6c79a91
Merge branch 'main' into psyqo_multitap_additions
johnbaumann Feb 20, 2025
c7ecace
Merge branch 'psyqo_multitap_additions' of https://github.com/johnbau…
johnbaumann Feb 20, 2025
6ee8271
Revert data type in processChanges
johnbaumann Feb 26, 2025
c61e2fb
Merge branch 'main' into psyqo_multitap_additions
johnbaumann Feb 27, 2025
0b1141a
Polyfill std::to_underlying and convert several static_casts
johnbaumann Feb 27, 2025
588f68d
Update utility-polyfill.h
johnbaumann Feb 27, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
122 changes: 95 additions & 27 deletions src/mips/psyqo/advancedpad.hh
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

MIT License

Copyright (c) 2024 PCSX-Redux authors
Copyright (c) 2025 PCSX-Redux authors

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand All @@ -29,6 +29,8 @@ SOFTWARE.
#include <EASTL/functional.h>
#include <stdint.h>

#include "psyqo/utility-polyfill.h"

namespace psyqo {

/**
Expand All @@ -42,7 +44,7 @@ namespace psyqo {

class AdvancedPad {
public:
enum Pad { Pad1a, Pad1b, Pad1c, Pad1d, Pad2a, Pad2b, Pad2c, Pad2d };
enum class Pad : unsigned { Pad1a, Pad1b, Pad1c, Pad1d, Pad2a, Pad2b, Pad2c, Pad2d };

enum Button {
Select = 0,
Expand All @@ -63,31 +65,17 @@ class AdvancedPad {
Square = 15,
};

enum Command : uint8_t {
PadSelect = 0x01,
ReadPad = 0x42, // 'B' Read Buttons AND analog inputs
// Config mode commands
ToggleConfigMode = 0x43, // 'C' Enter/Exit Configuration Mode
SetLED = 0x44, // 'D' Set LED State (analog mode on/off)
GetLED = 0x45, // 'E' Get LED State (and whatever values)
GetMotorInfo = 0x46, // 'F' Allegedly get info about a motor
GetMotorList = 0x47, // 'G' Allegedly get list of motors
GetMotorState = 0x48, // 'H' Allegedly get motor state
GetSupportedModes = 0x4c, // 'L' Allegedly get supported modes
ConfigRequestFormat = 0x4d, // 'M' Allegedly configure poll request format
ConfigResponseFormat = 0x4f, // 'O' Allegedly configure poll response format
};

enum PadType : uint8_t {
Mouse = 0x12, // (two button mouse)
NegCon = 0x23, // (steering twist/wheel/paddle)
KonamiLightgun = 0x31, // (IRQ10-type)
DigitalPad = 0x41, // (or analog pad/stick in digital mode; LED=Off)
AnalogStick = 0x53, // (or analog pad in "flight mode"; LED=Green)
NamcoLightgun = 0x63, // (Cinch-type)
NamcoLightGun = 0x63, // (Cinch-type)
AnalogPad = 0x73, // (in normal analog mode; LED=Red)
Multitap = 0x80, // (multiplayer adaptor) (when activated)
Jogcon = 0xe3, // (steering dial)
JogCon = 0xe3, // (steering dial)
FishingCon = 0xe5, // (fishing rod)
ConfigMode = 0xf3, // (when in config mode; see rumble command 43h)
None = 0xff // (no controller connected, pins floating High-Z)
};
Expand Down Expand Up @@ -143,7 +131,7 @@ class AdvancedPad {
* @param pad The pad to query.
* @return A boolean value indicating whether the pad is connected.
*/
bool isPadConnected(Pad pad) const { return (m_padData[pad][0] & 0xff) == 0; }
bool isPadConnected(Pad pad) const { return m_padData[toUnderlying(pad)].connected == 0; }

/**
* @brief Returns the state of a button.
Expand All @@ -155,23 +143,103 @@ class AdvancedPad {
* @param button The button to query.
* @return A boolean value indicating whether the button is pressed.
*/
bool isButtonPressed(Pad pad, Button button) const { return (m_padData[pad][1] & (1 << button)) == 0; }
bool isButtonPressed(Pad pad, Button button) const {
return (m_padData[toUnderlying(pad)].buttons & (1 << button)) == 0;
}

/**
* @brief Returns the state of an Analog Input.
*
* @details See the specific Analog Input functions for details.
* Indices greater than 3 will return 0.
* index 0: For analog pads: RightJoyX (00h=Left, 80h=Center, FFh=Right), mouse: X-axis
* index 1: For analog pads: RightJoyY (00h=Up, 80h=Center, FFh=Down), mouse: Y-axis
* index 2: For analog pads: LeftJoyX (00h=Left, 80h=Center, FFh=Right)
* index 3: For analog pads: LeftJoyY (00h=Up, 80h=Center, FFh=Down)
*
* @param pad The pad to query.
* @param index The index of the Analog Input(adc#).
* @return The state of the Analog Input as an unsigned 8-bit value(0-255).
*/
uint8_t getAdc(Pad pad, unsigned int index) const {
const unsigned padIndex = toUnderlying(pad);

return index <= 7 ? m_padData[padIndex].adc[index] : 0;
}

/**
* @brief Returns raw pad data as an unsigned 16-bit value.
*
* @details A low level call which returns the halfword value for the requested index of the given pad index.
* It is recommended to use the higher level functions instead.
* index 0: pad type << 8 | connected(0 = connected, ffh = disconnected)
* index 1: button state
* index 2: analog input 1 << 8 | analog input 0
* index 3: analog input 3 << 8 | analog input 2
* The index is modulo 4, so it will wrap around if it is greater than 3.
*
*
* @param pad The pad to query.
* @param index The index of the halfword.
* @return The value of the halfword.
*/

uint16_t getHalfword(Pad pad, unsigned int index) const { return m_padData[toUnderlying(pad)].packed[index % 4]; }

/**
* @brief Returns the type of the pad.
*
* @details Known pad types are defined in the PadType enum, returns 0xff if no pad is connected.
* PadType::Multitap is for internal use only, and should not be returned.
* Pad connection status should be checked with isPadConnected.
*
* @param pad The pad to query.
* @return The type of the pad.
*/
uint8_t getPadType(Pad pad) const { return m_padData[toUnderlying(pad)].padType; }

private:
enum Command : uint8_t {
PadSelect = 0x01,
ReadPad = 0x42, // 'B' Read Buttons AND analog inputs
// Config mode commands
ToggleConfigMode = 0x43, // 'C' Enter/Exit Configuration Mode
SetLED = 0x44, // 'D' Set LED State (analog mode on/off)
GetLED = 0x45, // 'E' Get LED State (and whatever values)
GetMotorInfo = 0x46, // 'F' Allegedly get info about a motor
GetMotorList = 0x47, // 'G' Allegedly get list of motors
GetMotorState = 0x48, // 'H' Allegedly get motor state
GetSupportedModes = 0x4c, // 'L' Allegedly get supported modes
ConfigRequestFormat = 0x4d, // 'M' Allegedly configure poll request format
ConfigResponseFormat = 0x4f, // 'O' Allegedly configure poll response format
};

void busyLoop(unsigned delay) {
unsigned cycles = 0;
while (++cycles < delay) asm("");
};

void configurePort(uint8_t port);

void flushRxBuffer();
uint8_t outputDefault(unsigned ticks);
uint8_t outputMultitap(unsigned ticks);
void processChanges(Pad pad);
void readPad();
uint8_t transceive(uint8_t data_out);
uint8_t transceive(uint8_t dataOut);
bool waitForAck(); // true if ack received, false if timeout

uint16_t m_padData[8][4];
union PadData {
struct {
uint8_t connected;
uint8_t padType;
uint16_t buttons;
uint8_t adc[8];
};
uint16_t packed[6];
};

PadData m_padData[8];
eastl::function<void(Event)> m_callback;
bool m_connected[8] = {false, false, false, false, false, false, false, false};
uint16_t m_buttons[8] = {
Expand All @@ -183,25 +251,25 @@ class AdvancedPad {

// prefix increment operator
inline psyqo::AdvancedPad::Pad& operator++(psyqo::AdvancedPad::Pad& pad) {
return pad = static_cast<psyqo::AdvancedPad::Pad>((static_cast<unsigned>(pad) + 1) & 7);
return pad = static_cast<psyqo::AdvancedPad::Pad>((toUnderlying(pad) + 1) & 7);
}

// postfix increment operator
inline psyqo::AdvancedPad::Pad operator++(psyqo::AdvancedPad::Pad& pad, int) {
psyqo::AdvancedPad::Pad copy(pad);
pad = static_cast<psyqo::AdvancedPad::Pad>((static_cast<unsigned>(pad) + 1) & 7);
pad = static_cast<psyqo::AdvancedPad::Pad>((toUnderlying(pad) + 1) & 7);
return copy;
}

// prefix decrement operator
inline psyqo::AdvancedPad::Pad& operator--(psyqo::AdvancedPad::Pad& pad) {
return pad = static_cast<psyqo::AdvancedPad::Pad>((static_cast<unsigned>(pad) - 1) & 7);
return pad = static_cast<psyqo::AdvancedPad::Pad>((toUnderlying(pad) - 1) & 7);
}

// postfix decrement operator
inline psyqo::AdvancedPad::Pad operator--(psyqo::AdvancedPad::Pad& pad, int) {
psyqo::AdvancedPad::Pad copy(pad);
pad = static_cast<psyqo::AdvancedPad::Pad>((static_cast<unsigned>(pad) - 1) & 7);
pad = static_cast<psyqo::AdvancedPad::Pad>((toUnderlying(pad) - 1) & 7);
return copy;
}

Expand Down
Loading
Loading