mirror of
https://github.com/TomHarte/CLK.git
synced 2025-04-12 20:37:11 +00:00
Sketches out the absolute basics of an SCC interface.
This commit is contained in:
parent
50d37798a2
commit
697e094a4e
49
Components/8530/z8530.cpp
Normal file
49
Components/8530/z8530.cpp
Normal 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
53
Components/8530/z8530.hpp
Normal 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 */
|
@ -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_;
|
||||
|
@ -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 */,
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user