Support Controller

This commit is contained in:
Jaby 2024-01-02 22:51:51 -06:00
parent ea71f4741f
commit 8b5ded2685
6 changed files with 152 additions and 16 deletions

View File

@ -24,7 +24,6 @@ static void setup() {
static void update() { static void update() {
Periphery::query_controller(); Periphery::query_controller();
FontWriter::FontWriter cursor; FontWriter::FontWriter cursor;
const auto end_pos = cursor.write(FontWriter::Position::create(0, 32), "Cody is cute\n&\na \x1b[8;0;0mBAAAAABY!!!"); const auto end_pos = cursor.write(FontWriter::Position::create(0, 32), "Cody is cute\n&\na \x1b[8;0;0mBAAAAABY!!!");

View File

@ -106,7 +106,9 @@ namespace JabyEngine {
return (ButtonState::was_down(button) && !ButtonState::is_down(button)); return (ButtonState::was_down(button) && !ButtonState::is_down(button));
} }
friend class RawController; friend class RawController;
friend struct ControllerHelper;
friend void query_controller();
}; };
Header header; Header header;

View File

@ -3,6 +3,15 @@
namespace JabyEngine { namespace JabyEngine {
namespace Periphery_IO { namespace Periphery_IO {
__declare_io_value(JOY_TX_DATA, uint32_t) {
static constexpr JOY_TX_DATA create(uint8_t byte) {
return JOY_TX_DATA{byte};
}
};
__declare_io_value(JOY_RX_DATA, uint8_t) {
};
__declare_io_value(JOY_STAT, uint32_t) { __declare_io_value(JOY_STAT, uint32_t) {
static constexpr auto TXReadyStart = Bit(0); static constexpr auto TXReadyStart = Bit(0);
static constexpr auto RXFifoNonEmpty = Bit(1); static constexpr auto RXFifoNonEmpty = Bit(1);
@ -48,8 +57,8 @@ namespace JabyEngine {
} }
}; };
__declare_io_port_w_type(, uint8_t, JOY_TX_DATA, 0x1F801040); __declare_io_port(, JOY_TX_DATA, 0x1F801040);
__declare_io_port_w_type(const, uint8_t, JOY_RX_DATA, 0x1F801040); __declare_io_port(const, JOY_RX_DATA, 0x1F801040);
__declare_io_port(const, JOY_STAT, 0x1F801044); __declare_io_port(const, JOY_STAT, 0x1F801044);
__declare_io_port(, JOY_MODE, 0x1F801048); __declare_io_port(, JOY_MODE, 0x1F801048);
__declare_io_port(, JOY_CTRL, 0x1F80104A); __declare_io_port(, JOY_CTRL, 0x1F80104A);

View File

@ -1,26 +1,34 @@
#pragma once #pragma once
#include <PSX/System/IOPorts/periphery_io.hpp>
#include <PSX/System/IOPorts/interrupt_io.hpp> #include <PSX/System/IOPorts/interrupt_io.hpp>
#include <PSX/System/IOPorts/periphery_io.hpp>
#include <PSX/Periphery/periphery.hpp>
#include <stdio.h>
extern "C" void busy_loop(int count);
namespace JabyEngine { namespace JabyEngine {
namespace Periphery { namespace Periphery {
using namespace Periphery_IO; using namespace Periphery_IO;
static void busy_cycle(uint32_t cycles) {
while(cycles--) {
asm("");
}
}
static void connect_to(uint16_t port) { static void connect_to(uint16_t port) {
JOY_CTRL.write(JOY_CTRL::create_for(port)); JOY_CTRL.write(JOY_CTRL::create_for(port));
busy_cycle(500); busy_loop(500);
} }
static void close_connection() { static void close_connection() {
JOY_CTRL.write(JOY_CTRL::close()); JOY_CTRL.write(JOY_CTRL::close());
} }
static void send_byte(uint8_t byte) {
while(!JOY_STAT.read().is_ready_transfer());
JOY_TX_DATA.write(JOY_TX_DATA::create(byte));
}
static uint8_t read_byte() {
while(!JOY_STAT.read().has_response());
return JOY_RX_DATA.read().raw;
}
static void acknowledge() { static void acknowledge() {
while(JOY_STAT.read().is_set(JOY_STAT::ACKIrqLow)); while(JOY_STAT.read().is_set(JOY_STAT::ACKIrqLow));
JOY_CTRL.write(JOY_CTRL.read().set(JOY_CTRL::ACK)); JOY_CTRL.write(JOY_CTRL.read().set(JOY_CTRL::ACK));

View File

@ -1,5 +1,6 @@
#include "../../internal-include/periphery_internal.hpp" #include "../../internal-include/periphery_internal.hpp"
#include <PSX/System/syscalls.hpp> #include <PSX/System/syscalls.hpp>
#include <stdio.h>
namespace JabyEngine { namespace JabyEngine {
namespace boot { namespace boot {
@ -9,8 +10,7 @@ namespace JabyEngine {
Periphery_IO::JOY_BAUD.write(Periphery_IO::JOY_BAUD::create()); Periphery_IO::JOY_BAUD.write(Periphery_IO::JOY_BAUD::create());
SysCall::EnterCriticalSection(); SysCall::EnterCriticalSection();
Interrupt::enable_irq(Interrupt::Periphery); Interrupt::disable_irq(Interrupt::Periphery);
Interrupt::ack_irq(Interrupt::Periphery);
SysCall::ExitCriticalSection(); SysCall::ExitCriticalSection();
} }
} }

View File

@ -1,3 +1,4 @@
#include "../../internal-include/periphery_internal.hpp"
#include <PSX/Periphery/periphery.hpp> #include <PSX/Periphery/periphery.hpp>
#include <stdio.h> #include <stdio.h>
@ -5,11 +6,128 @@ namespace JabyEngine {
namespace Periphery { namespace Periphery {
RawController controller[PortCount][DeviceCount]; RawController controller[PortCount][DeviceCount];
struct ControllerHelper {
static bool is_config(const RawController &cont) {
return (static_cast<uint8_t>(cont.header.state) & 0xF);
}
static void advance_config(RawController &cont) {
cont.header.state = static_cast<RawController::State>((static_cast<uint32_t>(cont.header.state) << 1));
}
static uint8_t* raw_device_data(RawController &cont) {
return reinterpret_cast<uint8_t*>(&cont.button.currentState);
}
};
static void set_config_command(RawController::State state, uint8_t (&header)[3], uint8_t (&data)[6]) {
static constexpr uint32_t CMDIDX = 1;
switch(state) {
case RawController::State::EnterConfigMode:
static constexpr uint8_t EnterCFGModeCMD = 0x1;
header[CMDIDX] = 0x43;
data[0] = EnterCFGModeCMD;
break;
case RawController::State::LockAnalog:
static constexpr uint8_t valID = 0;
static constexpr uint8_t selID = 1;
header[CMDIDX] = 0x44;
data[valID] = static_cast<uint8_t>(LED::State::On);
data[selID] = static_cast<uint8_t>(LED::Lock::On);
break;
case RawController::State::UnlockRumble:
header[CMDIDX] = 0x4D;
data[1] = 0x1;
for(int32_t n = 2; n < 6; n++) {
data[n] = 0xFF;
}
break;
case RawController::State::ExitConfigMode:
header[CMDIDX] = 0x43;
break;
}
}
static size_t send_data(const uint8_t* header, uint8_t* headerResponse, const uint8_t* data, uint8_t* response) {
const uint8_t *src = header;
uint8_t *dst = headerResponse;
size_t size = 3;
for(size_t n = 0; n < size; n++) {
Periphery::send_byte(*src);
Periphery::acknowledge();
*dst = Periphery::read_byte();
if(n == 2) {
const uint8_t id = headerResponse[1];
size += (id == 0xFF) ? 0 : ((id & 0xF) << 1);
src = data;
dst = response;
}
else {
src++;
dst++;
}
busy_loop(15);
}
return size;
}
void query_controller() { void query_controller() {
printf("Needs implementation\n"); static constexpr auto TypeIDX = 1;
for(uint32_t port = 0; port < Periphery::PortCount; port++) {
Periphery::connect_to(port);
for(uint32_t id = 0; id < Periphery::DeviceCount; id++) {
auto &cur_controller = controller[port][id];
uint8_t header[] = {static_cast<uint8_t>((id + 1)), 0x42, 0x0};
uint8_t data[] = {cur_controller.header.rumble0, cur_controller.header.rumble1, 0x0, 0x0, 0x0, 0x0};
// Can this move to the if??
set_config_command(cur_controller.header.state, header, data);
if(ControllerHelper::is_config(cur_controller)) {
send_data(header, header, data, data);
ControllerHelper::advance_config(cur_controller);
}
else {
cur_controller.button.exchange_state();
send_data(header, header, data, ControllerHelper::raw_device_data(cur_controller));
const bool isValidController = (header[TypeIDX] != 0xFF);
if(header[TypeIDX] != cur_controller.header.type) {
cur_controller.header.type = header[TypeIDX];
cur_controller.header.state = isValidController ? RawController::State::EnterConfigMode : RawController::State::Disconnected;
/*if(!isValidController)
{
printf("Disconnected!\n");
}
else
{
printf("ID: 0x%02X 0x%04X\n", header[TypeIDX], contData.button);
}*/
}
}
}
Periphery::close_connection();
}
} }
static_assert(!Configuration::Periphery::UsePortB, "Port B not supported yet"); static_assert(!Configuration::Periphery::UsePortB, "Port B not supported yet");
static_assert(!Configuration::Periphery::UseMultiTap, "MultiTap not supported yet"); static_assert(!Configuration::Periphery::UseMultiTap, "MultiTap not supported yet");
} }
} }