From 697e094a4e8b87c70c86fe084b69156fca42b9f5 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sat, 8 Jun 2019 18:47:11 -0400 Subject: [PATCH] Sketches out the absolute basics of an SCC interface. --- Components/8530/z8530.cpp | 49 +++++++++++++++++ Components/8530/z8530.hpp | 53 +++++++++++++++++++ Machines/Apple/Macintosh/Macintosh.cpp | 34 +++++++++--- .../Clock Signal.xcodeproj/project.pbxproj | 20 ++++++- .../Implementation/68000Implementation.hpp | 2 +- 5 files changed, 147 insertions(+), 11 deletions(-) create mode 100644 Components/8530/z8530.cpp create mode 100644 Components/8530/z8530.hpp diff --git a/Components/8530/z8530.cpp b/Components/8530/z8530.cpp new file mode 100644 index 000000000..c902f2055 --- /dev/null +++ b/Components/8530/z8530.cpp @@ -0,0 +1,49 @@ +// +// 8530.cpp +// Clock Signal +// +// Created by Thomas Harte on 07/06/2019. +// Copyright © 2019 Thomas Harte. All rights reserved. +// + +#include "z8530.hpp" + +using namespace Zilog::SCC; + +void z8530::reset() { +} + +std::uint8_t z8530::read(int address) { + return channels_[address & 1].read(address & 2); +} + +void z8530::write(int address, std::uint8_t value) { + channels_[address & 1].write(address & 2, pointer_, value); + + /* + Control register 0, which includes the pointer bits, + is decoded here because there's only one set of pointer bits. + */ + if(!(address & 2)) { + if(pointer_) { + pointer_ = 0; + } else { + pointer_ = value & 7; + } + } +} + +uint8_t z8530::Channel::read(bool data) { + // If this is a data read, just return it. + if(data) return data_; + + // Otherwise, this is a control read... + return 0x00; +} + +void z8530::Channel::write(bool data, uint8_t pointer, uint8_t value) { + if(data) { + data_ = value; + return; + } +} diff --git a/Components/8530/z8530.hpp b/Components/8530/z8530.hpp new file mode 100644 index 000000000..bc6ad248b --- /dev/null +++ b/Components/8530/z8530.hpp @@ -0,0 +1,53 @@ +// +// z8530.hpp +// Clock Signal +// +// Created by Thomas Harte on 07/06/2019. +// Copyright © 2019 Thomas Harte. All rights reserved. +// + +#ifndef z8530_hpp +#define z8530_hpp + +#include + +namespace Zilog { +namespace SCC { + +/*! + Models the Zilog 8530 SCC, a serial adaptor. +*/ +class z8530 { + public: + void reset(); + + /* + Notes on addressing below: + + There's no inherent ordering of the two 'address' lines, + A/B and C/D, but the methods below assume: + + A/B = A0 + C/D = A1 + */ + + std::uint8_t read(int address); + void write(int address, std::uint8_t value); + + private: + class Channel { + public: + uint8_t read(bool data); + void write(bool data, uint8_t pointer, uint8_t value); + + private: + uint8_t data_ = 0xff; + } channels_[2]; + uint8_t pointer_ = 0; +}; + +} +} + + +#endif /* z8530_hpp */ diff --git a/Machines/Apple/Macintosh/Macintosh.cpp b/Machines/Apple/Macintosh/Macintosh.cpp index 76e6f986b..e71cd4ec5 100644 --- a/Machines/Apple/Macintosh/Macintosh.cpp +++ b/Machines/Apple/Macintosh/Macintosh.cpp @@ -20,9 +20,10 @@ #include "../../CRTMachine.hpp" #include "../../MediaTarget.hpp" -//#define LOG_TRACE +#define LOG_TRACE #include "../../../Components/6522/6522.hpp" +#include "../../../Components/8530/z8530.hpp" #include "../../../Components/DiskII/IWM.hpp" #include "../../../Processors/68000/68000.hpp" @@ -179,7 +180,6 @@ template class ConcreteMachin // which at word precision is 0x77f0ff + register*256. if(cycle.operation & Microcycle::Read) { cycle.value->halves.low = via_.get_register(register_address); - if(cycle.operation & Microcycle::SelectWord) cycle.value->halves.high = 0xff; } else { via_.set_register(register_address, cycle.value->halves.low); } @@ -191,7 +191,6 @@ template class ConcreteMachin iwm_.flush(); if(cycle.operation & Microcycle::Read) { cycle.value->halves.low = iwm_.iwm.read(register_address); - if(cycle.operation & Microcycle::SelectWord) cycle.value->halves.high = 0xff; } else { iwm_.iwm.write(register_address, cycle.value->halves.low); } @@ -201,18 +200,34 @@ template class ConcreteMachin // Phase read. if(cycle.operation & Microcycle::Read) { cycle.value->halves.low = phase_ & 7; - if(cycle.operation & Microcycle::SelectWord) cycle.value->halves.high = 0xff; } break; case 0x480000: case 0x48f000: - case 0x500000: case 0x580000: case 0x58f000: + case 0x580000: case 0x58f000: // Any word access here adjusts phase. if(cycle.operation & Microcycle::SelectWord) { ++phase_; } else { - // TODO: SCC access. - printf("SCC access %06x\n", *cycle.address & 0xffffff); + if(word_address < 0x500000) { + // A0 = 1 => reset; A0 = 0 => read. + if(*cycle.address & 1) { + scc_.reset(); + } else { + const auto read = scc_.read(int(word_address)); + if(cycle.operation & Microcycle::Read) { + cycle.value->halves.low = read; + } + } + } else { + if(*cycle.address & 1) { + if(cycle.operation & Microcycle::Read) { + scc_.write(int(word_address), 0xff); + } else { + scc_.write(int(word_address), cycle.value->halves.low); + } + } + } } break; @@ -220,12 +235,12 @@ template class ConcreteMachin if(cycle.operation & Microcycle::Read) { printf("Unrecognised read %06x\n", *cycle.address & 0xffffff); cycle.value->halves.low = 0x00; - if(cycle.operation & Microcycle::SelectWord) cycle.value->halves.high = 0xff; } else { printf("Unrecognised write %06x\n", *cycle.address & 0xffffff); } break; } + if(cycle.operation & Microcycle::SelectWord) cycle.value->halves.high = 0xff; } } else { if(cycle.data_select_active()) { @@ -425,6 +440,7 @@ template class ConcreteMachin CA1 is used for receiving vsync maybe? */ if(port == Port::B && line == Line::Two) keyboard_.set_input(value); + else printf("Unhandled control line output: %c %d\n", port ? 'B' : 'A', int(line)); } void run_for(HalfCycles duration) { @@ -458,6 +474,8 @@ template class ConcreteMachin MOS::MOS6522::MOS6522 via_; VIAPortHandler via_port_handler_; + Zilog::SCC::z8530 scc_; + HalfCycles via_clock_; HalfCycles real_time_clock_; HalfCycles keyboard_clock_; diff --git a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj index f70f55113..15bd6a6e1 100644 --- a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj +++ b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj @@ -322,6 +322,8 @@ 4BB0A65E204500A900FB3688 /* StaticAnalyser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B7A90EC20410A85008514A2 /* StaticAnalyser.cpp */; }; 4BB17D4E1ED7909F00ABD1E1 /* tests.expected.json in Resources */ = {isa = PBXBuildFile; fileRef = 4BB17D4C1ED7909F00ABD1E1 /* tests.expected.json */; }; 4BB17D4F1ED7909F00ABD1E1 /* tests.in.json in Resources */ = {isa = PBXBuildFile; fileRef = 4BB17D4D1ED7909F00ABD1E1 /* tests.in.json */; }; + 4BB244D522AABAF600BE20E5 /* z8530.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BB244D322AABAF500BE20E5 /* z8530.cpp */; }; + 4BB244D622AABAF600BE20E5 /* z8530.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BB244D322AABAF500BE20E5 /* z8530.cpp */; }; 4BB298F11B587D8400A49093 /* start in Resources */ = {isa = PBXBuildFile; fileRef = 4BB297E51B587D8300A49093 /* start */; }; 4BB298F21B587D8400A49093 /* adca in Resources */ = {isa = PBXBuildFile; fileRef = 4BB297E61B587D8300A49093 /* adca */; }; 4BB298F31B587D8400A49093 /* adcax in Resources */ = {isa = PBXBuildFile; fileRef = 4BB297E71B587D8300A49093 /* adcax */; }; @@ -1073,6 +1075,8 @@ 4BB146C61F49D7D700253439 /* ClockingHintSource.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = ClockingHintSource.hpp; sourceTree = ""; }; 4BB17D4C1ED7909F00ABD1E1 /* tests.expected.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; name = tests.expected.json; path = FUSE/tests.expected.json; sourceTree = ""; }; 4BB17D4D1ED7909F00ABD1E1 /* tests.in.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; name = tests.in.json; path = FUSE/tests.in.json; sourceTree = ""; }; + 4BB244D322AABAF500BE20E5 /* z8530.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = z8530.cpp; sourceTree = ""; }; + 4BB244D422AABAF500BE20E5 /* z8530.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = z8530.hpp; sourceTree = ""; }; 4BB297E51B587D8300A49093 /* start */ = {isa = PBXFileReference; lastKnownFileType = file; path = " start"; sourceTree = ""; }; 4BB297E61B587D8300A49093 /* adca */ = {isa = PBXFileReference; lastKnownFileType = file; path = adca; sourceTree = ""; }; 4BB297E71B587D8300A49093 /* adcax */ = {isa = PBXFileReference; lastKnownFileType = file; path = adcax; sourceTree = ""; }; @@ -2523,6 +2527,15 @@ path = SN76489; sourceTree = ""; }; + 4BB244D222AABAF500BE20E5 /* 8530 */ = { + isa = PBXGroup; + children = ( + 4BB244D322AABAF500BE20E5 /* z8530.cpp */, + 4BB244D422AABAF500BE20E5 /* z8530.hpp */, + ); + path = 8530; + sourceTree = ""; + }; 4BB297E41B587D8300A49093 /* Wolfgang Lorenz 6502 test suite */ = { isa = PBXGroup; children = ( @@ -3030,8 +3043,6 @@ 4BC9DF4A1D04691600F44158 /* Components */ = { isa = PBXGroup; children = ( - 4B302181208A550100773308 /* DiskII */, - 4B595FAA2086DFBA0083CAA8 /* AudioToggle */, 4BD468F81D8DF4290084958B /* 1770 */, 4BC9DF4B1D04691600F44158 /* 6522 */, 4B1E85791D174DEC001EF87D /* 6532 */, @@ -3039,8 +3050,11 @@ 4BE845221F2FF7F400A5EA22 /* 6845 */, 4BD9137C1F3115AC009BCF85 /* 8255 */, 4BBC951F1F368D87008F4C34 /* 8272 */, + 4BB244D222AABAF500BE20E5 /* 8530 */, 4B0E04F71FC9F2C800F43484 /* 9918 */, + 4B595FAA2086DFBA0083CAA8 /* AudioToggle */, 4B4A762D1DB1A35C007AAE2E /* AY38910 */, + 4B302181208A550100773308 /* DiskII */, 4B4B1A39200198C900A0F866 /* KonamiSCC */, 4BB0A6582044FD3000FB3688 /* SN76489 */, ); @@ -3908,6 +3922,7 @@ 4B055AB51FAE860F0060FFFF /* TapePRG.cpp in Sources */, 4B055AE01FAE9B660060FFFF /* CRT.cpp in Sources */, 4B894527201967B4007DE474 /* StaticAnalyser.cpp in Sources */, + 4BB244D622AABAF600BE20E5 /* z8530.cpp in Sources */, 4BAF2B4F2004580C00480230 /* DMK.cpp in Sources */, 4B055AD01FAE9B030060FFFF /* Tape.cpp in Sources */, 4BD424E82193B5830097291A /* Rectangle.cpp in Sources */, @@ -4120,6 +4135,7 @@ 4B1B88C0202E3DB200B67DFF /* MultiConfigurable.cpp in Sources */, 4BFF1D3922337B0300838EA1 /* 68000Storage.cpp in Sources */, 4B54C0BC1F8D8E790050900F /* KeyboardMachine.cpp in Sources */, + 4BB244D522AABAF600BE20E5 /* z8530.cpp in Sources */, 4BB73EA21B587A5100552FC2 /* AppDelegate.swift in Sources */, 4B894534201967B4007DE474 /* AddressMapper.cpp in Sources */, 4B1B88C8202E469300B67DFF /* MultiJoystickMachine.cpp in Sources */, diff --git a/Processors/68000/Implementation/68000Implementation.hpp b/Processors/68000/Implementation/68000Implementation.hpp index 1fc1b13bb..0a6753110 100644 --- a/Processors/68000/Implementation/68000Implementation.hpp +++ b/Processors/68000/Implementation/68000Implementation.hpp @@ -284,7 +284,7 @@ template void Proces } #ifdef LOG_TRACE - should_log |= (program_counter_.full - 4) == 0x4181FA;//18A7A;//18AEE; + should_log |= (program_counter_.full - 4) == 0x418C22;//181FA;//18A7A;//18AEE; // should_log = ((program_counter_.full - 4) >= 0x417D9E) && ((program_counter_.full - 4) <= 0x419D96); #endif