diff --git a/ares/md/controller/control-pad/control-pad.cpp b/ares/md/controller/control-pad/control-pad.cpp index 8ba778c3af..255ed8a762 100644 --- a/ares/md/controller/control-pad/control-pad.cpp +++ b/ares/md/controller/control-pad/control-pad.cpp @@ -11,9 +11,7 @@ ControlPad::ControlPad(Node::Port parent) { start = node->append("Start"); } -auto ControlPad::readData() -> n8 { - n6 data; - +auto ControlPad::poll() -> void { platform->input(up); platform->input(down); platform->input(left); @@ -34,6 +32,10 @@ auto ControlPad::readData() -> n8 { } else if(!xHold) { xHold = 1, swap(leftLatch, rightLatch); } +} + +auto ControlPad::readData() -> Data { + n6 data; if(select == 0) { data.bit(0) = upLatch; @@ -51,10 +53,9 @@ auto ControlPad::readData() -> n8 { } data = ~data; - return latch << 7 | select << 6 | data; + return {data, 0x3f}; } auto ControlPad::writeData(n8 data) -> void { select = data.bit(6); - latch = data.bit(7); } diff --git a/ares/md/controller/control-pad/control-pad.hpp b/ares/md/controller/control-pad/control-pad.hpp index 0f4d4b86c5..cacec7a28e 100644 --- a/ares/md/controller/control-pad/control-pad.hpp +++ b/ares/md/controller/control-pad/control-pad.hpp @@ -10,12 +10,12 @@ struct ControlPad : Controller { ControlPad(Node::Port); - auto readData() -> n8 override; + auto poll() -> void override; + auto readData() -> Data override; auto writeData(n8 data) -> void override; private: n1 select = 1; - n1 latch; b1 yHold; b1 upLatch; diff --git a/ares/md/controller/controller.hpp b/ares/md/controller/controller.hpp index eadabb3018..a253d2ef4e 100644 --- a/ares/md/controller/controller.hpp +++ b/ares/md/controller/controller.hpp @@ -17,9 +17,15 @@ struct Controller { Node::Peripheral node; + struct Data { + n8 value; + n8 mask; + }; + virtual ~Controller() = default; - virtual auto readData() -> n8 { return 0xff; } + virtual auto poll() -> void {} + virtual auto readData() -> Data { return {0x7f, 0x7f}; } virtual auto writeData(n8 data) -> void {} }; diff --git a/ares/md/controller/fighting-pad/fighting-pad.cpp b/ares/md/controller/fighting-pad/fighting-pad.cpp index dc129b6c4b..7d5cb2d865 100644 --- a/ares/md/controller/fighting-pad/fighting-pad.cpp +++ b/ares/md/controller/fighting-pad/fighting-pad.cpp @@ -23,15 +23,13 @@ FightingPad::~FightingPad() { auto FightingPad::main() -> void { if(timeout) { - timeout--; - } else { - counter = 0; + if(!--timeout) counter = 0; } Thread::step(1); Thread::synchronize(cpu); } -auto FightingPad::readData() -> n8 { +auto FightingPad::poll() -> void { platform->input(up); platform->input(down); platform->input(left); @@ -56,7 +54,9 @@ auto FightingPad::readData() -> n8 { } else if(!xHold) { xHold = 1, swap(leftLatch, rightLatch); } +} +auto FightingPad::readData() -> Data { n6 data; if(select == 0) { @@ -82,8 +82,6 @@ auto FightingPad::readData() -> n8 { data.bit(1) = downLatch; data.bit(2) = leftLatch; data.bit(3) = rightLatch; - data.bit(4) = b->value(); - data.bit(5) = c->value(); } if(counter == 3) { @@ -91,20 +89,21 @@ auto FightingPad::readData() -> n8 { data.bit(1) = y->value(); data.bit(2) = x->value(); data.bit(3) = mode->value(); - data.bit(4,5) = 0; } + + data.bit(4) = b->value(); + data.bit(5) = c->value(); } data = ~data; - return latch << 7 | select << 6 | data; + return {data, 0x3f}; } auto FightingPad::writeData(n8 data) -> void { if(!select && data.bit(6)) { //0->1 transition - if(++counter == 5) counter = 0; + if(counter < 4) ++counter; + timeout = 1600; //~1.6ms } select = data.bit(6); - latch = data.bit(7); - timeout = 1600; //~1.6ms } diff --git a/ares/md/controller/fighting-pad/fighting-pad.hpp b/ares/md/controller/fighting-pad/fighting-pad.hpp index c8fa150099..bf9e4bcb59 100644 --- a/ares/md/controller/fighting-pad/fighting-pad.hpp +++ b/ares/md/controller/fighting-pad/fighting-pad.hpp @@ -15,12 +15,12 @@ struct FightingPad : Controller, Thread { FightingPad(Node::Port); ~FightingPad(); auto main() -> void; - auto readData() -> n8 override; + auto poll() -> void override; + auto readData() -> Data override; auto writeData(n8 data) -> void override; private: n1 select = 1; - n1 latch; n3 counter; n32 timeout; diff --git a/ares/md/controller/mega-mouse/mega-mouse.cpp b/ares/md/controller/mega-mouse/mega-mouse.cpp index 0360462717..8a98e60525 100644 --- a/ares/md/controller/mega-mouse/mega-mouse.cpp +++ b/ares/md/controller/mega-mouse/mega-mouse.cpp @@ -38,7 +38,6 @@ MegaMouse::MegaMouse(Node::Port parent) { t_data = 10 * timerfreq / 1000000; Thread::create(timerfreq, {&MegaMouse::main, this}); - Thread::synchronize(cpu); } MegaMouse::~MegaMouse() { @@ -68,7 +67,7 @@ auto MegaMouse::main() -> void { Thread::synchronize(cpu); } -auto MegaMouse::readData() -> n8 { +auto MegaMouse::readData() -> Data { n8 data; if (th) { @@ -81,14 +80,15 @@ auto MegaMouse::readData() -> n8 { } data.bit(4) = tl; - data.bit(5) = tr; - data.bit(6) = th; - data.bit(7) = latch; - return data; + return {data, 0x1f}; } auto MegaMouse::writeData(n8 data) -> void { + //todo: this check wouldn't be necessary if the logic below was correct. + //this function should only respond to level changes. + if(tr == data.bit(5) && th == data.bit(6)) return; + // Falling TH if (!data.bit(6) && th) { // When TH falls low, make sure the second nibble is driven. The @@ -142,6 +142,5 @@ auto MegaMouse::writeData(n8 data) -> void { timeout = t_handshake; } - latch = data.bit(7); th = data.bit(6); } diff --git a/ares/md/controller/mega-mouse/mega-mouse.hpp b/ares/md/controller/mega-mouse/mega-mouse.hpp index 12507afd43..97fbcc2a20 100644 --- a/ares/md/controller/mega-mouse/mega-mouse.hpp +++ b/ares/md/controller/mega-mouse/mega-mouse.hpp @@ -10,14 +10,13 @@ struct MegaMouse : Controller, Thread { ~MegaMouse(); auto main() -> void; - auto readData() -> n8 override; + auto readData() -> Data override; auto writeData(n8 data) -> void override; private: n1 th = 1; n1 tr = 1; n1 tl = 1; - n1 latch; n8 index = 0; n4 status[10]; s16 maxspeed = 255; diff --git a/ares/md/controller/port.cpp b/ares/md/controller/port.cpp index 185fbbda66..208e692311 100644 --- a/ares/md/controller/port.cpp +++ b/ares/md/controller/port.cpp @@ -29,10 +29,21 @@ auto ControllerPort::allocate(string name) -> Node::Peripheral { return {}; } +auto ControllerPort::update() -> void { + auto [inputData, inputMask] = device ? device->readData() : Controller::Data{0x7f, 0x7f}; + n8 outputMask = 0x80 | control; + n8 prevLines = dataLines; + dataLines = inputData & inputMask | dataLines & ~inputMask; + dataLines = dataLatch & outputMask | dataLines & ~outputMask; + //todo: gradually pull up floating lines + if(device && prevLines != dataLines) return device->writeData(dataLines); +} + auto ControllerPort::power(bool reset) -> void { if(!reset) { control = 0x00; dataLatch = 0x7f; + dataLines = 0x7f; serialControl = 0x00; serialTxBuffer = 0xff; serialRxBuffer = 0x00; @@ -42,6 +53,7 @@ auto ControllerPort::power(bool reset) -> void { auto ControllerPort::serialize(serializer& s) -> void { s(control); s(dataLatch); + s(dataLines); s(serialControl); s(serialTxBuffer); s(serialRxBuffer); diff --git a/ares/md/controller/port.hpp b/ares/md/controller/port.hpp index f12f49fbec..132cc5f340 100644 --- a/ares/md/controller/port.hpp +++ b/ares/md/controller/port.hpp @@ -11,17 +11,17 @@ struct ControllerPort { auto connect(Node::Peripheral) -> void; auto disconnect() -> void { device.reset(); } + auto update() -> void; + auto readControl() -> n8 { return control; } - auto writeControl(n8 data) -> void { control = data; } + auto writeControl(n8 data) -> void { control = data; update(); } auto readData() -> n8 { - n8 data = device ? device->readData() : n8(~0); - return dataLatch = dataLatch & (0x80 | control) | data & ~(0x80 | control); - } - auto writeData(n8 data) -> void { - dataLatch = dataLatch & ~(0x80 | control) | data & (0x80 | control); - if(device) return device->writeData(dataLatch); + if(device) device->poll(); + update(); + return dataLines; } + auto writeData(n8 data) -> void { dataLatch = data; update(); } // TODO: Implement working serial transfers. This code is mostly placeholder. @@ -57,6 +57,7 @@ struct ControllerPort { const string name; n8 control; //d0-d6 = PC0-PC6 (0 = input; 1 = output); d7 = TH-INT enable n8 dataLatch; + n8 dataLines; n8 serialControl; n8 serialTxBuffer; n8 serialRxBuffer; diff --git a/ares/md/system/serialization.cpp b/ares/md/system/serialization.cpp index 21efa43191..b70b16a483 100644 --- a/ares/md/system/serialization.cpp +++ b/ares/md/system/serialization.cpp @@ -1,4 +1,4 @@ -static const string SerializerVersion = "v133.1"; +static const string SerializerVersion = "v134"; auto System::serialize(bool synchronize) -> serializer { if(synchronize) scheduler.enter(Scheduler::Mode::Synchronize);