1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-06-25 18:30:07 +00:00

Formalise the idea of Grauw as a separate clock.

This commit is contained in:
Thomas Harte 2023-05-18 16:37:48 -04:00
parent 4cb7abe13d
commit c76048bff9
3 changed files with 102 additions and 68 deletions

View File

@ -11,14 +11,21 @@
#include "../9918.hpp"
#include "PersonalityTraits.hpp"
#include "LineLayout.hpp"
namespace TI::TMS {
enum class Clock {
/// Whatever rate this VDP runs at, with location 0 being "the start" of the line per internal preference.
Internal,
/// A 342-cycle/line clock with the same start position as ::Internal.
TMSPixel,
/// A 171-cycle/line clock that begins at the memory window which starts straight after ::Internal = 0.
TMSMemoryWindow,
CRT
/// A fixed 1368-cycle/line clock that is used to count output to the CRT.
CRT,
/// Provides the same clock rate as ::Internal but is relocated so that 0 is where Grauw put 0 (i.e. at the start of horizontal sync).
Grauw,
};
template <Personality personality, Clock clk> constexpr int clock_rate() {
@ -33,6 +40,7 @@ template <Personality personality, Clock clk> constexpr int clock_rate() {
case Clock::TMSMemoryWindow: return 171;
case Clock::CRT: return 1368;
case Clock::Internal:
case Clock::Grauw:
if constexpr (is_classic_vdp(personality)) {
return 342;
} else if constexpr (is_yamaha_vdp(personality)) {
@ -43,17 +51,25 @@ template <Personality personality, Clock clk> constexpr int clock_rate() {
}
}
/// Statelessly converts @c length in @c clock to the internal clock used by VDPs of @c personality throwing away any remainder.
template <Personality personality, Clock clock> constexpr int to_internal(int length) {
if constexpr (clock == Clock::Grauw) {
return (length + LineLayout<personality>::LocationOfGrauwZero) % LineLayout<personality>::CyclesPerLine;
}
return length * clock_rate<personality, Clock::Internal>() / clock_rate<personality, clock>();
}
/// Statelessly converts @c length to @c clock from the the internal clock used by VDPs of @c personality throwing away any remainder.
template <Personality personality, Clock clock> constexpr int from_internal(int length) {
if constexpr (clock == Clock::Grauw) {
return (length + LineLayout<personality>::CyclesPerLine - LineLayout<personality>::LocationOfGrauwZero) % LineLayout<personality>::CyclesPerLine;
}
return length * clock_rate<personality, clock>() / clock_rate<personality, Clock::Internal>();
}
/*!
Provides a [potentially-]stateful conversion between the external and internal clocks.
Unlike the other clock conversions, this one may be non-integral, requiring that
Unlike the other clock conversions, this may be non-integral, requiring that
an error term be tracked.
*/
template <Personality personality> class ClockConverter {
@ -130,72 +146,6 @@ template <Personality personality> class ClockConverter {
int cycles_error_ = 0;
};
//
//
//
template <Personality personality, typename Enable = void> struct LineLayout;
// Line layout is:
//
// [0, EndOfSync] sync
// (EndOfSync, StartOfColourBurst] blank
// (StartOfColourBurst, EndOfColourBurst] colour burst
// (EndOfColourBurst, EndOfLeftErase] blank
// (EndOfLeftErase, EndOfLeftBorder] border colour
// (EndOfLeftBorder, EndOfPixels] pixel content
// (EndOfPixels, EndOfRightBorder] border colour
// [EndOfRightBorder, <end of line>] blank
//
// ... with minor caveats:
// * horizontal adjust on the Yamaha VDPs is applied to EndOfLeftBorder and EndOfPixels;
// * the Sega VDPs may programatically extend the left border; and
// * text mode on all VDPs adjusts border width.
template <Personality personality> struct LineLayout<personality, std::enable_if_t<is_classic_vdp(personality)>> {
constexpr static int EndOfSync = 26;
constexpr static int StartOfColourBurst = 29;
constexpr static int EndOfColourBurst = 43;
constexpr static int EndOfLeftErase = 50;
constexpr static int EndOfLeftBorder = 63;
constexpr static int EndOfPixels = 319;
constexpr static int EndOfRightBorder = 334;
constexpr static int CyclesPerLine = 342;
constexpr static int TextModeEndOfLeftBorder = 69;
constexpr static int TextModeEndOfPixels = 309;
constexpr static int ModeLatchCycle = 36; // Just a guess; correlates with the known 144 for the Yamaha VDPs,
// and falls into the collection gap between the final sprite
// graphics and the initial tiles or pixels.
/// The number of internal cycles that must elapse between a request to read or write and
/// it becoming a candidate for action.
constexpr static int VRAMAccessDelay = 6;
};
template <Personality personality> struct LineLayout<personality, std::enable_if_t<is_yamaha_vdp(personality)>> {
constexpr static int EndOfSync = 100;
constexpr static int StartOfColourBurst = 113;
constexpr static int EndOfColourBurst = 167;
constexpr static int EndOfLeftErase = 202;
constexpr static int EndOfLeftBorder = 258;
constexpr static int EndOfPixels = 1282;
constexpr static int EndOfRightBorder = 1341;
constexpr static int CyclesPerLine = 1368;
constexpr static int TextModeEndOfLeftBorder = 294;
constexpr static int TextModeEndOfPixels = 1254;
constexpr static int ModeLatchCycle = 144;
/// The number of internal cycles that must elapse between a request to read or write and
/// it becoming a candidate for action.
constexpr static int VRAMAccessDelay = 16;
};
}
#endif /* ClockConverter_hpp */

View File

@ -0,0 +1,82 @@
//
// LineLayout.hpp
// Clock Signal
//
// Created by Thomas Harte on 18/05/2023.
// Copyright © 2023 Thomas Harte. All rights reserved.
//
#ifndef LineLayout_h
#define LineLayout_h
namespace TI::TMS {
template <Personality personality, typename Enable = void> struct LineLayout;
// Line layout is:
//
// [0, EndOfSync] sync
// (EndOfSync, StartOfColourBurst] blank
// (StartOfColourBurst, EndOfColourBurst] colour burst
// (EndOfColourBurst, EndOfLeftErase] blank
// (EndOfLeftErase, EndOfLeftBorder] border colour
// (EndOfLeftBorder, EndOfPixels] pixel content
// (EndOfPixels, EndOfRightBorder] border colour
// [EndOfRightBorder, <end of line>] blank
//
// ... with minor caveats:
// * horizontal adjust on the Yamaha VDPs is applied to EndOfLeftBorder and EndOfPixels;
// * the Sega VDPs may programatically extend the left border; and
// * text mode on all VDPs adjusts border width.
template <Personality personality> struct LineLayout<personality, std::enable_if_t<is_classic_vdp(personality)>> {
constexpr static int EndOfSync = 26;
constexpr static int StartOfColourBurst = 29;
constexpr static int EndOfColourBurst = 43;
constexpr static int EndOfLeftErase = 50;
constexpr static int EndOfLeftBorder = 63;
constexpr static int EndOfPixels = 319;
constexpr static int EndOfRightBorder = 334;
constexpr static int CyclesPerLine = 342;
constexpr static int TextModeEndOfLeftBorder = 69;
constexpr static int TextModeEndOfPixels = 309;
constexpr static int ModeLatchCycle = 36; // Just a guess; correlates with the known 144 for the Yamaha VDPs,
// and falls into the collection gap between the final sprite
// graphics and the initial tiles or pixels.
constexpr static int LocationOfGrauwZero = 0;
/// The number of internal cycles that must elapse between a request to read or write and
/// it becoming a candidate for action.
constexpr static int VRAMAccessDelay = 6;
};
template <Personality personality> struct LineLayout<personality, std::enable_if_t<is_yamaha_vdp(personality)>> {
constexpr static int EndOfSync = 100;
constexpr static int StartOfColourBurst = 113;
constexpr static int EndOfColourBurst = 167;
constexpr static int EndOfLeftErase = 202;
constexpr static int EndOfLeftBorder = 258;
constexpr static int EndOfPixels = 1282;
constexpr static int EndOfRightBorder = 1341;
constexpr static int CyclesPerLine = 1368;
constexpr static int TextModeEndOfLeftBorder = 294;
constexpr static int TextModeEndOfPixels = 1254;
constexpr static int ModeLatchCycle = 144;
constexpr static int LocationOfGrauwZero = 0;
/// The number of internal cycles that must elapse between a request to read or write and
/// it becoming a candidate for action.
constexpr static int VRAMAccessDelay = 16;
};
}
#endif /* LineLayout_h */

View File

@ -1100,6 +1100,7 @@
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
428168372A16C25C008ECD27 /* LineLayout.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = LineLayout.hpp; sourceTree = "<group>"; };
42AD552E2A0C4D5000ACE410 /* 68000.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = 68000.hpp; sourceTree = "<group>"; };
42AD55302A0C4D5000ACE410 /* 68000Storage.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = 68000Storage.hpp; sourceTree = "<group>"; };
42AD55312A0C4D5000ACE410 /* 68000Implementation.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = 68000Implementation.hpp; sourceTree = "<group>"; };
@ -4738,6 +4739,7 @@
4B43983F2967459B006B0BFC /* Draw.hpp */,
4B43983E29628538006B0BFC /* Fetch.hpp */,
4B2A3B5B29995FF6007CE366 /* LineBuffer.hpp */,
428168372A16C25C008ECD27 /* LineLayout.hpp */,
4B262BFF29691F55002EC0F7 /* PersonalityTraits.hpp */,
4B2A3B5A29993DFA007CE366 /* Storage.hpp */,
4BF0BC732982E54700CCA2B5 /* YamahaCommands.hpp */,