*
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
# Prerequisites
|
||||
*.d
|
||||
|
||||
# Compiled Object files
|
||||
*.slo
|
||||
*.lo
|
||||
*.o
|
||||
*.obj
|
||||
|
||||
# Precompiled Headers
|
||||
*.gch
|
||||
*.pch
|
||||
|
||||
# Compiled Dynamic libraries
|
||||
*.so
|
||||
*.dylib
|
||||
*.dll
|
||||
|
||||
# Fortran module files
|
||||
*.mod
|
||||
*.smod
|
||||
|
||||
# Compiled Static libraries
|
||||
*.lai
|
||||
*.la
|
||||
*.a
|
||||
*.lib
|
||||
|
||||
# Executables
|
||||
*.exe
|
||||
*.out
|
||||
*.app
|
||||
Vendored
+16
@@ -0,0 +1,16 @@
|
||||
|
||||
|
||||
add_library(LibPad INTERFACE)
|
||||
|
||||
target_include_directories(LibPad
|
||||
INTERFACE
|
||||
Src
|
||||
)
|
||||
|
||||
target_sources(LibPad
|
||||
INTERFACE
|
||||
Src/LibPad/PsIoPhy.h
|
||||
Src/LibPad/PsIo.h
|
||||
Src/LibPad/PsMemCard.h
|
||||
Src/LibPad/PsPad.h
|
||||
)
|
||||
Vendored
+21
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2020 Sergey Serb
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
Vendored
+8
@@ -0,0 +1,8 @@
|
||||
SOURCES += $$files($$PWD/src/*.cpp, true) \
|
||||
$$PWD/src/LibPad/PsPad.c
|
||||
SOURCES += $$files($$PWD/src/*.c, true)
|
||||
HEADERS += $$files($$PWD/src/*.h, true) \
|
||||
$$PWD/src/LibPad/PsIo.h \
|
||||
$$PWD/src/LibPad/PsMemCard.h \
|
||||
$$PWD/src/LibPad/PsPad.h
|
||||
INCLUDEPATH += $$PWD/Src
|
||||
Vendored
+19
@@ -0,0 +1,19 @@
|
||||
# LibPad
|
||||
Low-level PS1/PS2 gamepad communication library (mostly for embedded usage)
|
||||
|
||||
## Data interface
|
||||
It is just SPI: LSB first, CPOL=1, CPHA=1
|
||||
|
||||
## Pad pinout
|
||||
|
||||
| Pin number | Pin name | Meaning |
|
||||
| ------------- | ------------------ |------------------------------------------------|
|
||||
| 1 | DATA [Open-drain!] | Data from joypad/memory card (SPI_MISO on MCU). Open drain (requires pull-up) |
|
||||
| 2 | CMD | Data to joypad/memory card (SPI_MOSI on MCU) |
|
||||
| 3 | +7.6V | Power supply for vibration motors |
|
||||
| 4 | GND | Ground |
|
||||
| 5 | VCC | 3.6V (should work fine with 3.3V) |
|
||||
| 6 | ATT | Attention (SPI_CS on MCU) |
|
||||
| 7 | CLK | Clock (SPI_CLK on MCU) PS1: 250KHz for controller and memory card, 500KHz or 1MHz for multitap. PS2: 250KHz for controller, 25MHz for memory card |
|
||||
| 8 | N/C [IRQ10] | Joy only (Konami Justifier). Typically not connected |
|
||||
| 9 | Ack [IRQ7] [Open-drain!]| Goes low for at least 1 clock after each 8 bits transmitted with 60us timeout . Open drain (requires pull-up)|
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include "PsIoPhy.h"
|
||||
|
||||
struct PsIoBuffer {
|
||||
uint8_t size;
|
||||
uint8_t data[200] = {};
|
||||
};
|
||||
|
||||
struct PsIoPort {
|
||||
uint8_t id;
|
||||
PsIoPhy* phy;
|
||||
PsIoBuffer rxBuffer;
|
||||
|
||||
inline bool psIoPortExecuteCommand(uint8_t* cmd, uint8_t cmdSize) {
|
||||
uint8_t i;
|
||||
|
||||
if(!phy->begin()){
|
||||
return false;
|
||||
}
|
||||
|
||||
rxBuffer.size = 0;
|
||||
for(i = 0; i < cmdSize; ++i){
|
||||
if(!phy->shift(cmd[i], &rxBuffer.data[i])){
|
||||
break;
|
||||
}
|
||||
rxBuffer.size = i + 1;
|
||||
}
|
||||
|
||||
phy->end();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
struct PsIoPhy {
|
||||
virtual ~PsIoPhy() = default;
|
||||
virtual bool begin() = 0;
|
||||
virtual bool shift(uint8_t txData, uint8_t* rxData) = 0;
|
||||
virtual void end() = 0;
|
||||
};
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
#pragma once
|
||||
|
||||
#include "PsIo.h"
|
||||
#include <string.h>
|
||||
|
||||
#define PS_MEM_CARD_BLOCK_STATE_BEGIN 0xA1
|
||||
#define PS_MEM_CARD_BLOCK_STATE_MIDDLE 0xA2
|
||||
#define PS_MEM_CARD_BLOCK_STATE_END 0xA2
|
||||
#define PS_MEM_CARD_BLOCK_STATE_FORMATTED 0xA0
|
||||
#define PS_MEM_CARD_BLOCK_STATE_BEGIN_DELETED 0xA1
|
||||
#define PS_MEM_CARD_BLOCK_STATE_MIDDLE_DELETED 0xA2
|
||||
#define PS_MEM_CARD_BLOCK_STATE_END_DELETED 0xA2
|
||||
|
||||
struct PsMemCard {
|
||||
uint8_t slot;
|
||||
struct PsIoPort* port;
|
||||
};
|
||||
|
||||
int psMemCardReadId(struct PsMemCard* memcard){
|
||||
uint8_t cmd[] = { memcard->slot, 0x53, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
return psIoPortExecuteCommand(memcard->port, cmd, sizeof(cmd));
|
||||
}
|
||||
|
||||
int psMemCardRead(struct PsMemCard* memcard, uint16_t addr, uint8_t* rxBuffer128){ //Addr: 0..3FFh
|
||||
int error;
|
||||
|
||||
uint8_t cmd[10 + 128 + 2];
|
||||
memset(cmd, 0, sizeof(cmd));
|
||||
|
||||
cmd[0] = memcard->slot;
|
||||
cmd[1] = 0x52;
|
||||
cmd[4] = (uint8_t)((addr & 0xff00) >> 8);
|
||||
cmd[5] = (uint8_t)(addr & 0xff);
|
||||
|
||||
error = psIoPortExecuteCommand(memcard->port, cmd, sizeof(cmd));
|
||||
if(!error){
|
||||
memcpy(rxBuffer128, &memcard->port->rxBuffer.data[10], 128);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
+73
@@ -0,0 +1,73 @@
|
||||
#pragma once
|
||||
|
||||
#include "PsIo.h"
|
||||
|
||||
struct PsPad {
|
||||
uint8_t slot = 0x01;
|
||||
struct PsIoPort* port;
|
||||
|
||||
//(SCPH-1010)
|
||||
inline bool psPadPollDigital(){
|
||||
uint8_t cmd[5] = {slot, 0x42, 0x00, 0x00, 0x00};
|
||||
return port->psIoPortExecuteCommand(cmd, sizeof(cmd));
|
||||
}
|
||||
|
||||
// (SCPH-1110) or (SCPH-1180)
|
||||
inline bool psPadPollAnalog(){
|
||||
uint8_t cmd[9] = {slot, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
return port->psIoPortExecuteCommand(cmd, sizeof(cmd));
|
||||
}
|
||||
|
||||
// DualShock 1,2 (SCPH-1180, SCPH-1200, SCPH-10010)
|
||||
inline bool psPadPollAnalogRumble(std::uint8_t rightMotor, std::uint8_t leftMotor){
|
||||
uint8_t cmd[9] = {slot, 0x42, 0x00, 0x00, 0x00, rightMotor, leftMotor, 0x00, 0x00};
|
||||
return port->psIoPortExecuteCommand(cmd, sizeof(cmd));
|
||||
}
|
||||
|
||||
// DualShock 2 SCPH-10010
|
||||
inline bool psPadPollDualshock2(){
|
||||
uint8_t cmd[21] = {slot, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
return port->psIoPortExecuteCommand(cmd, sizeof(cmd));
|
||||
}
|
||||
|
||||
|
||||
inline int psPadSetDataMask(uint8_t b0, uint8_t b1, uint8_t b2) {
|
||||
uint8_t cmd[] = { slot, 0x4F, 0x00, b0, b1, b2, 0x00, 0x00, 0x00 };
|
||||
return port->psIoPortExecuteCommand(cmd, sizeof(cmd));
|
||||
}
|
||||
|
||||
inline int psPadConfigEnter() {
|
||||
uint8_t cmd[] = { slot, 0x43, 0x00, 0x01, 0x00};
|
||||
return port->psIoPortExecuteCommand(cmd, sizeof(cmd));
|
||||
}
|
||||
|
||||
inline int psPadConfigExit() {
|
||||
uint8_t cmd[] = { slot, 0x43, 0x00, 0x00, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A };
|
||||
return port->psIoPortExecuteCommand(cmd, sizeof(cmd));
|
||||
}
|
||||
|
||||
inline int psPadConfigQueryModel() { //no args 100%
|
||||
uint8_t cmd[9] = { slot, 0x45, 0x00, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A };
|
||||
return port->psIoPortExecuteCommand(cmd, sizeof(cmd));
|
||||
}
|
||||
|
||||
inline int psPadConfigQueryAct(uint8_t b1) { //b1 = index
|
||||
uint8_t cmd[9] = { slot, 0x46, 0x00, b1, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A };
|
||||
return port->psIoPortExecuteCommand(cmd, sizeof(cmd));
|
||||
}
|
||||
|
||||
inline int psPadConfigQueryComb(uint8_t b1) { //b1 - maybe index, not failed but single record
|
||||
uint8_t cmd[9] = { slot, 0x47, 0x00, b1, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A };
|
||||
return port->psIoPortExecuteCommand(cmd, sizeof(cmd));
|
||||
}
|
||||
|
||||
inline int psPadConfigQueryMode(uint8_t b1) { //byte #6 - supported mode, b1 = index
|
||||
uint8_t cmd[9] = { slot, 0x4c, 0x00, b1, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A };
|
||||
return port->psIoPortExecuteCommand(cmd, sizeof(cmd));
|
||||
}
|
||||
|
||||
inline int psPadSetControllerMode(uint8_t analog, uint8_t lockMode) {
|
||||
uint8_t cmd[] = { slot, 0x44, 0x00, (uint8_t)(analog ? 0x01 : 0x00), (uint8_t)(lockMode ? 0x03 : 0x5A), 0x00, 0x00, 0x00, 0x00 };
|
||||
return port->psIoPortExecuteCommand(cmd, sizeof(cmd));
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user