From 7e6d4f5a3e37a9594141e295ceab98f4ab683902 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Wed, 8 May 2019 00:12:19 -0400 Subject: [PATCH] Adds emulation of the real-time clock. --- .../Implementation/6522Implementation.hpp | 4 +- Machines/Apple/Macintosh/Macintosh.cpp | 48 ++++++++++++++++--- .../Clock Signal.xcodeproj/project.pbxproj | 2 + 3 files changed, 46 insertions(+), 8 deletions(-) diff --git a/Components/6522/Implementation/6522Implementation.hpp b/Components/6522/Implementation/6522Implementation.hpp index 4e3074032..5db653ba1 100644 --- a/Components/6522/Implementation/6522Implementation.hpp +++ b/Components/6522/Implementation/6522Implementation.hpp @@ -71,14 +71,14 @@ template void MOS6522::set_register(int address, uint8_t value) // TODO: simplify below; trying to avoid improper logging of unimplemented warnings in input mode if(value & 0x08) { switch(value & 0x0e) { - default: LOG("Unimplemented control line mode " << int((value >> 1)&7)); break; + default: LOG("Unimplemented control CA2 line mode " << int((value >> 1)&7)); break; case 0x0c: bus_handler_.set_control_line_output(Port::A, Line::Two, false); break; case 0x0e: bus_handler_.set_control_line_output(Port::A, Line::Two, true); break; } } if(value & 0x80) { switch(value & 0xe0) { - default: LOG("Unimplemented control line mode " << int((value >> 5)&7)); break; + default: LOG("Unimplemented control CB2 line mode " << int((value >> 5)&7)); break; case 0xc0: bus_handler_.set_control_line_output(Port::B, Line::Two, false); break; case 0xe0: bus_handler_.set_control_line_output(Port::B, Line::Two, true); break; } diff --git a/Machines/Apple/Macintosh/Macintosh.cpp b/Machines/Apple/Macintosh/Macintosh.cpp index 372a9a36a..beb060aae 100644 --- a/Machines/Apple/Macintosh/Macintosh.cpp +++ b/Machines/Apple/Macintosh/Macintosh.cpp @@ -11,6 +11,7 @@ #include #include "Video.hpp" +#include "RealTimeClock.hpp" #include "../../CRTMachine.hpp" @@ -20,6 +21,12 @@ #include "../../Utility/MemoryPacker.hpp" +namespace { + +const int CLOCK_RATE = 7833600; + +} + namespace Apple { namespace Macintosh { @@ -32,8 +39,8 @@ class ConcreteMachine: mc68000_(*this), video_(ram_.data()), via_(via_port_handler_), - via_port_handler_(*this), - iwm_(7833600) { + via_port_handler_(*this, clock_), + iwm_(CLOCK_RATE) { // Grab a copy of the ROM and convert it into big-endian data. const auto roms = rom_fetcher("Macintosh", { "mac128k.rom" }); @@ -44,7 +51,7 @@ class ConcreteMachine: Memory::PackBigEndian16(*roms[0], rom_.data()); // The Mac runs at 7.8336mHz. - set_clock_rate(7833600.0); + set_clock_rate(double(CLOCK_RATE)); } void set_scan_target(Outputs::Display::ScanTarget *scan_target) override { @@ -72,6 +79,19 @@ class ConcreteMachine: // TODO: SCC is a divide-by-two. + // Consider updating the real-time clock. + real_time_clock_ += cycle.length; + auto ticks = real_time_clock_.divide_cycles(Cycles(CLOCK_RATE)).as_int(); + while(ticks--) { + clock_.update(); + // TODO: leave a delay between toggling the input rather than using this coupled hack. + via_.set_control_line_input(MOS::MOS6522::Port::A, MOS::MOS6522::Line::Two, true); + via_.set_control_line_input(MOS::MOS6522::Port::A, MOS::MOS6522::Line::Two, false); + } + + // Update interrupt input. TODO: move this into a VIA/etc delegate callback? + mc68000_.set_interrupt_level( (via_.get_interrupt_line() ? 1 : 0) ); + // A null cycle leaves nothing else to do. if(cycle.operation) { auto word_address = cycle.word_address(); @@ -192,9 +212,13 @@ class ConcreteMachine: } private: + class Keyboard { + public: + }; + class VIAPortHandler: public MOS::MOS6522::PortHandler { public: - VIAPortHandler(ConcreteMachine &machine) : machine_(machine) {} + VIAPortHandler(ConcreteMachine &machine, RealTimeClock &clock) : machine_(machine), clock_(clock) {} using Port = MOS::MOS6522::Port; using Line = MOS::MOS6522::Line; @@ -232,7 +256,8 @@ class ConcreteMachine: b1: clock's data-clock line b0: clock's serial data line */ -// printf("6522 B: %02x\n", value); + if(value & 0x4) clock_.abort(); + else clock_.set_input(!!(value & 0x2), !!(value & 0x1)); break; } } @@ -245,16 +270,24 @@ class ConcreteMachine: case Port::B: // printf("6522 r B\n"); - return 0x00; + return (clock_.get_data() ? 0x02 : 0x00); } } void set_control_line_output(Port port, Line line, bool value) { + /* + Keyboard wiring (I believe): + CB2 = data + CB1 = clock + + CA2 is used for receiving RTC interrupts. + */ // printf("6522 line %c%d: %c\n", port ? 'B' : 'A', int(line), value ? 't' : 'f'); } private: ConcreteMachine &machine_; + RealTimeClock &clock_; }; std::array rom_; @@ -263,6 +296,8 @@ class ConcreteMachine: CPU::MC68000::Processor mc68000_; Video video_; + RealTimeClock clock_; + MOS::MOS6522::MOS6522 via_; VIAPortHandler via_port_handler_; @@ -271,6 +306,7 @@ class ConcreteMachine: HalfCycles via_clock_; HalfCycles time_since_video_update_; HalfCycles time_since_iwm_update_; + HalfCycles real_time_clock_; bool ROM_is_overlay_ = true; }; diff --git a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj index 809caf46c..2393d521a 100644 --- a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj +++ b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj @@ -1390,6 +1390,7 @@ 4BCF1FA21DADC3DD0039D2E7 /* Oric.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Oric.cpp; path = Oric/Oric.cpp; sourceTree = ""; }; 4BCF1FA31DADC3DD0039D2E7 /* Oric.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = Oric.hpp; path = Oric/Oric.hpp; sourceTree = ""; }; 4BD060A51FE49D3C006E14BE /* Speaker.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Speaker.hpp; sourceTree = ""; }; + 4BD0692B22828A2D00D2A54F /* RealTimeClock.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = RealTimeClock.hpp; sourceTree = ""; }; 4BD191D9219113B80042E144 /* OpenGL.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = OpenGL.hpp; sourceTree = ""; }; 4BD191F22191180E0042E144 /* ScanTarget.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ScanTarget.cpp; sourceTree = ""; }; 4BD191F32191180E0042E144 /* ScanTarget.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = ScanTarget.hpp; sourceTree = ""; }; @@ -3070,6 +3071,7 @@ 4BCE0058227CFFCA000CA200 /* Macintosh.cpp */, 4BCE005E227D39AB000CA200 /* Video.cpp */, 4BCE0059227CFFCA000CA200 /* Macintosh.hpp */, + 4BD0692B22828A2D00D2A54F /* RealTimeClock.hpp */, 4BCE005F227D39AB000CA200 /* Video.hpp */, ); path = Macintosh;