|
|
1.1 root 1: //
2: // nono
1.1.1.4 root 3: // Copyright (C) 2020 nono project
4: // Licensed under nono-license.txt
1.1 root 5: //
6:
1.1.1.8 root 7: //
8: // CRTC-II (HD6445)
9: //
10:
1.1 root 11: #include "crtc2.h"
12: #include "renderer.h"
1.1.1.8 root 13: #include "scheduler.h"
1.1 root 14:
1.1.1.8 root 15: // グローバル参照用
16: CRTC2Device *gCRTC2;
1.1.1.6 root 17:
1.1.1.8 root 18: // コンストラクタ
1.1 root 19: CRTC2Device::CRTC2Device()
1.1.1.7 root 20: : inherited("CRTC2")
1.1 root 21: {
22: devaddr = 0xd1000000;
23:
1.1.1.8 root 24: vdisp_event.func = ToEventCallback(&CRTC2Device::VDispCallback);
25: vdisp_event.Regist("CRTC2 V-DISP");
1.1 root 26: }
27:
1.1.1.8 root 28: // デストラクタ
1.1 root 29: CRTC2Device::~CRTC2Device()
30: {
1.1.1.8 root 31: gCRTC2 = NULL;
1.1 root 32: }
33:
1.1.1.8 root 34: // リセット
1.1 root 35: void
1.1.1.8 root 36: CRTC2Device::ResetHard(bool poweron)
1.1 root 37: {
38: // リセット信号で初期化されるレジスタ (他は維持)
39: reg[30] = 0;
40: reg[31] = 0;
41: reg[32] = 0;
42:
43: // 未確認
44: ar = 0;
45:
46: // XXX 適当
47: // すぐに垂直帰線期間を開始する
48: vdisp_event.time = 0;
49: vdisp_event.code = 1;
1.1.1.8 root 50: gScheduler->RestartEvent(vdisp_event);
1.1 root 51: }
52:
53: uint64
1.1.1.6 root 54: CRTC2Device::Read(uint32 offset)
1.1 root 55: {
56: uint32 data;
57:
1.1.1.6 root 58: switch (offset) {
1.1 root 59: case 0: // アドレスレジスタ
60: // アドレスレジスタは書き込み専用
61: // XXX 何が読めるか
62: data = 0xff;
1.1.1.9 ! root 63: putlog(1, "Read write-only register AR");
1.1 root 64: break;
65:
66: case 1: // データレジスタ
67: switch (ar) {
68: case 12 ... 25: // 読み出し可能
69: case 28 ... 31:
70: case 33:
71: case 36 ... 39:
72: data = reg[ar];
73: putlog(2, "R%02d -> $%02x", ar, data);
74: break;
75:
76: case 40 ... 63: // 範囲外
77: // 未使用レジスタの読み出しは $00 (p.17)
78: data = 0;
1.1.1.9 ! root 79: putlog(1, "Read unused register R%02d", ar);
1.1 root 80: break;
81:
82: default: // 書き込み専用レジスタ
83: // 読み出しは 0 になる (p.112)
84: data = 0;
1.1.1.9 ! root 85: putlog(1, "Read write-only register R%02d", ar);
1.1 root 86: break;
87: }
88: break;
89:
90: default:
1.1.1.3 root 91: __unreachable();
1.1 root 92: }
93: return data;
94: }
95:
96: uint64
1.1.1.6 root 97: CRTC2Device::Write(uint32 offset, uint32 data)
1.1 root 98: {
1.1.1.6 root 99: switch (offset) {
1.1 root 100: case 0: // アドレスレジスタ
101: ar = data & 0x3f;
1.1.1.9 ! root 102: putlog(3, "Address Register <- $%02x", ar);
1.1 root 103: return 0;
104:
105: case 1: // データレジスタ
106: switch (ar) {
107: case 16 ... 17: // 読み出し専用レジスタ
108: case 28:
1.1.1.9 ! root 109: putlog(1, "Write read-only register R%02d <- $%02x", ar, data);
1.1 root 110: break;
111:
112: case 40 ... 63: // 範囲外
1.1.1.9 ! root 113: putlog(1, "Write unused register R%02d <- $%02x", ar, data);
1.1 root 114: break;
115:
116: default: // 書き込み可能レジスタ
117: reg[ar] = data;
118: putlog(2, "R%02d <- $%02x", ar, data);
119: break;
120: }
121: return 0;
122:
123: default:
1.1.1.3 root 124: __unreachable();
1.1 root 125: }
126: }
127:
128: uint64
1.1.1.6 root 129: CRTC2Device::Peek(uint32 offset)
1.1 root 130: {
1.1.1.6 root 131: switch (offset) {
1.1 root 132: case 0: // アドレスレジスタ
133: return ar;
134:
135: case 1: // データレジスタ
136: return reg[ar];
137:
138: default:
1.1.1.3 root 139: __unreachable();
1.1 root 140: }
141: }
142:
143: // 垂直表示・帰線イベント
1.1.1.5 root 144: // ev.code が 1 なら表示期間開始(V-disp)、0 なら帰線期間開始(V-blank)。
1.1 root 145: void
1.1.1.5 root 146: CRTC2Device::VDispCallback(Event& ev)
1.1 root 147: {
1.1.1.5 root 148: int& vdisp = ev.code;
149:
1.1 root 150: // 今はここで1画面まるごと作成
1.1.1.5 root 151: if (vdisp) {
1.1 root 152: // Render に作画指示
153: gRenderer->Render();
154: }
155:
156: // 次のタイミングを計算
157: // XXX まだ CRTC から計算していない
1.1.1.5 root 158: if (vdisp) {
1.1 root 159: // 垂直表示期間
1.1.1.5 root 160: ev.time = 16234.496_usec; // 1024*Ht
161: ev.code = 0;
1.1 root 162: } else {
163: // 垂直帰線期間
1.1.1.5 root 164: ev.time = 507.328_usec; // 32*Ht
165: ev.code = 1;
1.1 root 166: }
1.1.1.8 root 167: gScheduler->StartEvent(ev);
1.1 root 168: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.