|
|
1.1 root 1: //
2: // nono
3: // Copyright (C) 2020 nono project
4: // Licensed under nono-license.txt
5: //
6:
7: //
8: // LUNA LCD パネル
9: //
10:
11: #include "wxlcdwindow.h"
12: #include "wxcolor.h"
13: #include "wxtextscreen.h"
14: #include "lcd.h"
15:
16: // パネルの大きさ (定数)
17: // N はとりあえずの倍率。
18: #define N (2)
19: #define PANEL_WIDTH ((N) * (5 + 1) * 16 + 1)
20: #define PANEL_HEIGHT ((N) * (8 + 1) * 2 + 1)
21:
22: //
23: // LUNA LCD パネル
24: //
25:
26: // イベントテーブル
27: wxBEGIN_EVENT_TABLE(WXLCDPanel, inherited)
28: EVT_TIMER(wxID_ANY, WXLCDPanel::OnTimer)
29: EVT_PAINT(WXLCDPanel::OnPaint)
30: wxEND_EVENT_TABLE()
31:
32: // コンストラクタ
33: WXLCDPanel::WXLCDPanel(wxWindow *parent)
34: : inherited(parent, wxID_ANY, wxDefaultPosition,
35: wxSize(PANEL_WIDTH, PANEL_HEIGHT))
36: {
37: bmpbuf.reset(new uint8 [PANEL_WIDTH * PANEL_HEIGHT * 3]);
38: memset(&bmpbuf[0], 0x70, PANEL_WIDTH * PANEL_HEIGHT * 3);
39: image.reset(new wxImage(PANEL_WIDTH, PANEL_HEIGHT, bmpbuf.get(), true));
40: bitmap.reset(new wxBitmap(*image));
41:
42: count = (uint32)-1;
43: ddram = gLCD->GetDDRAM();
44:
45: // 更新タイマー。そんなに応答速度速くなくていい
46: timer.SetOwner(this);
47: timer.Start(50);
48: }
49:
50: // デストラクタ
51: WXLCDPanel::~WXLCDPanel()
52: {
53: bitmap.reset();
54: image.reset();
55: bmpbuf.reset();
56: }
57:
58: // タイマーイベント
59: void
60: WXLCDPanel::OnTimer(wxTimerEvent& event)
61: {
62: uint32 devcount;
63:
64: // 更新があれば..
65: devcount = gLCD->GetCounter();
66: if (count != devcount) {
67: count = devcount;
68:
69: // 再描画を起こす
70: Refresh();
71: }
72: }
73:
74: // 描画イベント (UI スレッドから呼ばれる)
75: void
76: WXLCDPanel::OnPaint(wxPaintEvent& event)
77: {
78: // メモリ DC に描画
79: wxMemoryDC memDC;
80: memDC.SelectObject(*bitmap);
81: Draw(memDC);
82:
83: // 実画面 DC にコピー
84: wxPaintDC dstDC(this);
85: dstDC.Blit(0, 0, PANEL_WIDTH, PANEL_HEIGHT, &memDC, 0, 0);
86: }
87:
88: // バックグラウンドバッファに描画
89: void
90: WXLCDPanel::Draw(wxDC& dc)
91: {
92: // 背景
93: dc.SetPen(UD_CREAM);
94: dc.SetBrush(UD_CREAM);
95: dc.DrawRectangle(wxPoint(0, 0), wxSize(PANEL_WIDTH, PANEL_HEIGHT));
96:
97: for (int y = 0; y < 2; y++) {
98: for (int x = 0; x < 16; x++) {
99: uint8 ch = ddram[0x40 * y + x];
100: DrawChar(dc, x, y, ch);
101: }
102: }
103: }
104:
105: // 1文字描画
106: void
107: WXLCDPanel::DrawChar(wxDC& dc, int x, int y, uint8 ch)
108: {
109: wxSize dotsize = wxSize(N, N);
110: const uint8 *font;
111:
112: font = gLCD->GetFont(ch);
113:
114: for (int py = 0; py < 8; py++) {
115: uint8 line = *font++;
116: line <<= 3;
117: for (int px = 0; px < 5; px++) {
118: wxColour color;
119: if ((int8)line < 0) {
120: color = UD_BROWN;
121: } else {
122: color = UD_YELLOW_GREEN;
123: }
124: dc.SetPen(color);
125: dc.SetBrush(color);
126: dc.DrawRectangle(
127: wxPoint((1 + x * 6 + px) * N, (1 + y * 9 + py) * N),
128: dotsize);
129:
130: line <<= 1;
131: }
132: }
133: }
134:
135: //
136: // LCD ウィンドウ
137: //
138:
139: // コンストラクタ
140: WXLCDWindow::WXLCDWindow(wxWindow *parent, wxWindowID id)
141: : inherited(parent, id, _("Front LCD"))
142: {
143: panel = new WXLCDPanel(this);
144:
145: // 大きさをそれに固定
146: Layout();
147: Fit();
148: }
149:
150: // デストラクタ
151: WXLCDWindow::~WXLCDWindow()
152: {
153: }
154:
155: //
156: // LCD キャラクタパネル
157: //
158:
159: #define CP_WIDTH (N * (1 + 6 * 16))
160: #define CP_HEIGHT (N * (1 + 9 * 16))
161:
162: // イベントテーブル
163: wxBEGIN_EVENT_TABLE(WXLCDCharPanel, inherited)
164: EVT_PAINT(WXLCDCharPanel::OnPaint)
165: wxEND_EVENT_TABLE()
166:
167: // コンストラクタ
168: WXLCDCharPanel::WXLCDCharPanel(wxWindow *parent)
169: : inherited(parent, wxID_ANY, wxDefaultPosition,
170: wxSize(CP_WIDTH, CP_HEIGHT))
171: {
172: bmpbuf.reset(new uint8 [CP_WIDTH * CP_HEIGHT * 3]);
173: memset(&bmpbuf[0], 0x70, CP_WIDTH * CP_HEIGHT * 3);
174: image.reset(new wxImage(CP_WIDTH, CP_HEIGHT, bmpbuf.get(), true));
175: bitmap.reset(new wxBitmap(*image));
176: }
177:
178: // デストラクタ
179: WXLCDCharPanel::~WXLCDCharPanel()
180: {
181: bitmap.reset();
182: image.reset();
183: bmpbuf.reset();
184: }
185:
186: // 描画イベント (UI スレッドから呼ばれる)
187: void
188: WXLCDCharPanel::OnPaint(wxPaintEvent& event)
189: {
190: // メモリ DC に描画
191: wxMemoryDC memDC;
192: memDC.SelectObject(*bitmap);
193: Draw(memDC);
194:
195: // 実画面 DC にコピー
196: wxPaintDC dstDC(this);
197: dstDC.Blit(0, 0, CP_WIDTH, CP_HEIGHT, &memDC, 0, 0);
198: }
199:
200: // バックグラウンドバッファに描画
201: void
202: WXLCDCharPanel::Draw(wxDC& dc)
203: {
204: wxSize dotsize = wxSize(N, N);
205:
206: // 背景
207: // XXX LIGHT_GREY を textscreen と共用すること
208: dc.SetPen(*wxLIGHT_GREY);
209: dc.SetBrush(*wxLIGHT_GREY);
210: dc.DrawRectangle(wxPoint(0, 0), wxSize(CP_WIDTH, CP_HEIGHT));
211:
212: // フォントは 5x8 (最下行はカーソル用に空けてあるので実際は 5x7)。
213: // 実際には 0xe0 以降には 5x10 フォントが混在しているのだが、その
214: // モードはサポートしていないので今の所全部 5x8 としてある。
215: for (int ch = 0; ch < 256; ch++) {
216: // この文字の左上座標 (スケール前)
217: int cx = 1 + (ch % 16) * 6;
218: int cy = 1 + (ch / 16) * 9;
219:
220: const uint8 *font = gLCD->GetFont(ch);
221: for (int py = 0; py < 8; py++) {
222: uint8 line = *font++;
223: line <<= 3;
224: for (int px = 0; px < 5; px++) {
225: wxColour color;
226: if ((int8)line < 0) {
227: color = *wxBLACK;
228: } else {
229: color = *wxWHITE;
230: }
231: dc.SetPen(color);
232: dc.SetBrush(color);
233: dc.DrawRectangle(
234: wxPoint((cx + px) * N, (cy + py) * N),
235: dotsize);
236:
237: line <<= 1;
238: }
239: }
240: }
241: }
242:
243: //
244: // LCD モニタウィンドウ
245: //
246:
247: // コンストラクタ
248: WXLCDMonitor::WXLCDMonitor(wxWindow *parent, wxWindowID id)
249: : inherited(parent, id, _("LCD"))
250: {
251: wxBoxSizer *topsizer = new wxBoxSizer(wxVERTICAL);
252:
253: monpanel = new WXTextScreen(this, *gLCD);
254: topsizer->Add(monpanel, 0, wxEXPAND | wxALL, DefaultPadding);
255:
256: chrpanel = new WXLCDCharPanel(this);
257: topsizer->Add(chrpanel, 0, wxEXPAND | wxRIGHT | wxLEFT | wxBOTTOM,
258: DefaultPadding);
259:
260: SetSizer(topsizer);
261:
262: // 大きさをそれに固定
263: Layout();
264: Fit();
265: }
266:
267: // デストラクタ
268: WXLCDMonitor::~WXLCDMonitor()
269: {
270: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.