1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-09-27 02:55:07 +00:00

Sketches out the absolute basics of an SCC interface.

This commit is contained in:
Thomas Harte 2019-06-08 18:47:11 -04:00
parent 50d37798a2
commit 697e094a4e
5 changed files with 147 additions and 11 deletions

49
Components/8530/z8530.cpp Normal file
View File

@ -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;
}
}

53
Components/8530/z8530.hpp Normal file
View File

@ -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 <cstdint>
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 */

View File

@ -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 <Analyser::Static::Macintosh::Target::Model model> 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 <Analyser::Static::Macintosh::Target::Model model> 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 <Analyser::Static::Macintosh::Target::Model model> 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 <Analyser::Static::Macintosh::Target::Model model> 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 <Analyser::Static::Macintosh::Target::Model model> 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 <Analyser::Static::Macintosh::Target::Model model> class ConcreteMachin
MOS::MOS6522::MOS6522<VIAPortHandler> via_;
VIAPortHandler via_port_handler_;
Zilog::SCC::z8530 scc_;
HalfCycles via_clock_;
HalfCycles real_time_clock_;
HalfCycles keyboard_clock_;

View File

@ -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 = "<group>"; };
4BB17D4C1ED7909F00ABD1E1 /* tests.expected.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; name = tests.expected.json; path = FUSE/tests.expected.json; sourceTree = "<group>"; };
4BB17D4D1ED7909F00ABD1E1 /* tests.in.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; name = tests.in.json; path = FUSE/tests.in.json; sourceTree = "<group>"; };
4BB244D322AABAF500BE20E5 /* z8530.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = z8530.cpp; sourceTree = "<group>"; };
4BB244D422AABAF500BE20E5 /* z8530.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = z8530.hpp; sourceTree = "<group>"; };
4BB297E51B587D8300A49093 /* start */ = {isa = PBXFileReference; lastKnownFileType = file; path = " start"; sourceTree = "<group>"; };
4BB297E61B587D8300A49093 /* adca */ = {isa = PBXFileReference; lastKnownFileType = file; path = adca; sourceTree = "<group>"; };
4BB297E71B587D8300A49093 /* adcax */ = {isa = PBXFileReference; lastKnownFileType = file; path = adcax; sourceTree = "<group>"; };
@ -2523,6 +2527,15 @@
path = SN76489;
sourceTree = "<group>";
};
4BB244D222AABAF500BE20E5 /* 8530 */ = {
isa = PBXGroup;
children = (
4BB244D322AABAF500BE20E5 /* z8530.cpp */,
4BB244D422AABAF500BE20E5 /* z8530.hpp */,
);
path = 8530;
sourceTree = "<group>";
};
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 */,

View File

@ -284,7 +284,7 @@ template <class T, bool dtack_is_implicit, bool signal_will_perform> 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