OXYGENHUB
◆ main openmsx / src / video / v9990 / V9990DisplayTiming.hh
3.0 KiB · C++ · last changed chore(): initial commit 1 month ago source blame history raw
1
#ifndef V9990DISPLAYTIMING_HH
2
#define V9990DISPLAYTIMING_HH
3
4
namespace openmsx {
5
6
/** A period, either horizontal or vertical, starts with a synchronisation
7
  * pulse followed by a blank period. Then border, display and border are
8
  * output follow. The final blank between the last border period and the
9
  * following sync signal is not included -- we don't need it.
10
  */
11
struct V9990DisplayPeriod
12
{
13
	int cycle;
14
	int blank;
15
	int border1;
16
	int display;
17
	int border2;
18
};
19
20
class V9990DisplayTiming
21
{
22
public:
23
	/** The V9990 has an internal clock (MCLK @ 14MHz) and a terminal
24
	  * for an external clock (XTAL1), which can be connected to a 21
25
	  * or 25 MHz crystal. The Gfx9000 provides an 21 MHz crystal.
26
	  *
27
	  * The emulation combines these two clocks into one unified
28
	  * clock (UC) running at 42MHz - the smallest common multiple
29
	  * of 14 and 21 MHz.
30
	  */
31
	static constexpr int UC_TICKS_PER_SECOND = 3579545 * 12; // 42.9MHz
32
33
	/** The number of clock ticks per line is independent of the crystal
34
	  * used or the display mode (NTSC/PAL)
35
	  */
36
	static constexpr int UC_TICKS_PER_LINE = 2736;
37
38
	/** Horizontal (line) timing when using MCLK:
39
	  * 'Normal' display modes. Timing is in UC ticks.
40
	  */
41
	static constexpr auto lineMCLK = V9990DisplayPeriod{
42
		.cycle = V9990DisplayTiming::UC_TICKS_PER_LINE, .blank = 400, .border1 = 112, .display = 2048, .border2 = 112};
43
44
	/** Horizontal (line) timing when using XTAL:
45
	  *'Overscan' modes without border. Timing is in UC ticks.
46
	  */
47
	static constexpr auto lineXTAL = V9990DisplayPeriod{
48
		.cycle = V9990DisplayTiming::UC_TICKS_PER_LINE, .blank = 372, .border1 = 0, .display = 2304, .border2 = 0};
49
50
	/** NTSC display timing, when using MCLK:
51
	  * Normal display mode with borders. Timing is in display lines.
52
	  */
53
	static constexpr auto displayNTSC_MCLK = V9990DisplayPeriod{
54
		.cycle = 262, .blank = 15, .border1 = 14, .display = 212, .border2 = 14};
55
56
	/** NTSC display timing, when using XTAL:
57
	  * Overscan mode without borders. Timing is in display lines.
58
	  */
59
	static constexpr auto displayNTSC_XTAL = V9990DisplayPeriod{
60
		.cycle = 262, .blank = 15, .border1 = 0, .display = 240, .border2 = 0};
61
62
	/** PAL display timing, when using MCLK:
63
	  * Normal display mode with borders. Timing is in display lines.
64
	  */
65
	static constexpr auto displayPAL_MCLK = V9990DisplayPeriod{
66
		.cycle = 313, .blank = 15, .border1 = 41, .display = 212, .border2 = 37};
67
68
	/** PAL display timing, when using XTAL:
69
	  * Overscan mode without borders. Timing is in display lines.
70
	  */
71
	static constexpr auto displayPAL_XTAL = V9990DisplayPeriod{
72
		.cycle = 313, .blank = 15, .border1 = 0, .display = 290, .border2 = 0};
73
74
75
	/** Get the number of UC ticks in 1 frame.
76
	  * @param  palTiming  Use PAL timing? (False = NTSC timing)
77
	  * @return            The number of UC ticks in a frame
78
	  */
79
	[[nodiscard]] static constexpr int getUCTicksPerFrame(bool palTiming) {
80
		return palTiming ? (displayPAL_MCLK.cycle  * UC_TICKS_PER_LINE)
81
		                 : (displayNTSC_MCLK.cycle * UC_TICKS_PER_LINE);
82
	}
83
};
84
85
} // openmsx
86
87
#endif