Skip to content

Commit b644308

Browse files
committed
mu5: Add the lc7985nd and the lcd [O. Galibert]
1 parent b210948 commit b644308

File tree

6 files changed

+482
-0
lines changed

6 files changed

+482
-0
lines changed

scripts/src/video.lua

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -603,6 +603,18 @@ if (VIDEOS["LC7582"]~=null) then
603603
}
604604
end
605605

606+
--------------------------------------------------
607+
--
608+
--@src/devices/video/lc7985.h,VIDEOS["LC7985"] = true
609+
--------------------------------------------------
610+
611+
if (VIDEOS["LC7985"]~=null) then
612+
files {
613+
MAME_DIR .. "src/devices/video/lc7985.cpp",
614+
MAME_DIR .. "src/devices/video/lc7985.h",
615+
}
616+
end
617+
606618
--------------------------------------------------
607619
--
608620
--@src/devices/video/m50458.h,VIDEOS["M50458"] = true

scripts/target/mame/arcade.lua

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,7 @@ VIDEOS["I4100"] = true
336336
VIDEOS["I8275"] = true
337337
VIDEOS["JANGOU_BLITTER"] = true
338338
--VIDEOS["LC7582"] = true
339+
--VIDEOS["LC7985"] = true
339340
VIDEOS["M50458"] = true
340341
VIDEOS["MB90082"] = true
341342
VIDEOS["MB_VCU"] = true

scripts/target/mame/mess.lua

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,7 @@ VIDEOS["I82730"] = true
366366
VIDEOS["I8275"] = true
367367
VIDEOS["IMS_CVC"] = true
368368
VIDEOS["LC7582"] = true
369+
VIDEOS["LC7985"] = true
369370
--VIDEOS["M50458"] = true
370371
--VIDEOS["MB90082"] = true
371372
--VIDEOS["MB_VCU"] = true

src/devices/video/lc7985.cpp

Lines changed: 302 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,302 @@
1+
// license:BSD-3-Clause
2+
// copyright-holders:Olivier Galibert
3+
/***************************************************************************
4+
5+
Sanyo LC7985NA/LC7985ND LCD controller
6+
7+
***************************************************************************/
8+
9+
#include "emu.h"
10+
#include "lc7985.h"
11+
12+
DEFINE_DEVICE_TYPE(LC7985, lc7985_device, "lc7985", "Sanyo LC7985NA/LC7985ND LCD controller")
13+
14+
15+
ROM_START( lc7985 )
16+
ROM_REGION( 0x1000, "cgrom", 0 )
17+
ROM_LOAD( "lc7985.bin", 0x0000, 0x1000, BAD_DUMP CRC(fdc64160) SHA1(8e6b54f8fb7c4c15aab2e65dd1a44729b97423b1)) // from page 12 of the LC7985D datasheet
18+
ROM_END
19+
20+
lc7985_device::lc7985_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
21+
: device_t(mconfig, LC7985, tag, owner, clock),
22+
m_cgrom_region(*this, DEVICE_SELF)
23+
{
24+
}
25+
26+
const tiny_rom_entry *lc7985_device::device_rom_region() const
27+
{
28+
return ROM_NAME(lc7985);
29+
}
30+
31+
void lc7985_device::device_start()
32+
{
33+
m_cgrom = m_cgrom_region.found() ? m_cgrom_region : memregion("cgrom")->base();
34+
m_busy_timer = timer_alloc(0);
35+
36+
save_item(NAME(m_ddram));
37+
save_item(NAME(m_cgram));
38+
save_item(NAME(m_busy_flag));
39+
save_item(NAME(m_ddac));
40+
save_item(NAME(m_cgac));
41+
save_item(NAME(m_shift));
42+
save_item(NAME(m_access_ddram));
43+
save_item(NAME(m_function));
44+
save_item(NAME(m_cds));
45+
}
46+
47+
void lc7985_device::device_reset()
48+
{
49+
memset(m_ddram, 0x20, sizeof(m_ddram)); // filled with SPACE char
50+
memset(m_cgram, 0, sizeof(m_cgram));
51+
m_ddac = 0x00;
52+
m_cgac = 0x00;
53+
m_shift = 0x00;
54+
m_access_ddram = false;
55+
m_function = 0x00;
56+
m_cds = 0x00;
57+
m_display = 0x00;
58+
m_entry = 0x02;
59+
60+
busy(attotime::from_msec(10));
61+
}
62+
63+
void lc7985_device::busy(attotime time)
64+
{
65+
m_busy_flag = true;
66+
m_busy_timer->adjust(time);
67+
}
68+
69+
void lc7985_device::device_timer(emu_timer &, device_timer_id, int, void *)
70+
{
71+
m_busy_flag = false;
72+
}
73+
74+
void lc7985_device::inc_ddac()
75+
{
76+
if(m_function & 0x08) { // 2 lines
77+
if(m_ddac == 39)
78+
m_ddac = 64;
79+
else if(m_ddac == 64+39)
80+
m_ddac = 0;
81+
else
82+
m_ddac++;
83+
} else {
84+
if(m_ddac == 79)
85+
m_ddac = 0;
86+
else
87+
m_ddac++;
88+
}
89+
}
90+
91+
void lc7985_device::dec_ddac()
92+
{
93+
if(m_function & 0x08) { // 2 lines
94+
if(m_ddac == 64)
95+
m_ddac = 39;
96+
else if(m_ddac == 0)
97+
m_ddac = 64+39;
98+
else
99+
m_ddac--;
100+
} else {
101+
if(m_ddac == 0)
102+
m_ddac = 79;
103+
else
104+
m_ddac--;
105+
}
106+
}
107+
108+
void lc7985_device::shift_left()
109+
{
110+
if(m_shift == 79)
111+
m_shift = 0;
112+
else
113+
m_shift++;
114+
}
115+
116+
void lc7985_device::shift_right()
117+
{
118+
if(m_shift == 0)
119+
m_shift = 79;
120+
else
121+
m_shift--;
122+
}
123+
124+
void lc7985_device::ir_w(u8 data)
125+
{
126+
if(m_busy_flag)
127+
return;
128+
129+
if(data & 0x80) {
130+
// Set DDRAM address
131+
m_ddac = data & 0x7f;
132+
m_access_ddram = true;
133+
busy(attotime::from_usec(40));
134+
135+
} else if(data & 0x40) {
136+
// Set CGRAM address
137+
m_cgac = data & 0x3f;
138+
m_access_ddram = false;
139+
busy(attotime::from_usec(40));
140+
141+
} else if(data & 0x20) {
142+
// Set Function
143+
m_function = data;
144+
busy(attotime::from_usec(40));
145+
146+
} else if(data & 0x10) {
147+
// Cursor/Display Shift
148+
m_access_ddram = true;
149+
switch((data >> 2) & 3) {
150+
case 0: dec_ddac(); break;
151+
case 1: inc_ddac(); break;
152+
case 2: shift_left(); break;
153+
case 3: shift_right(); break;
154+
}
155+
156+
busy(attotime::from_usec(40));
157+
158+
} else if(data & 0x08) {
159+
// Display On/Off
160+
m_display = data;
161+
busy(attotime::from_usec(40));
162+
163+
} else if(data & 0x04) {
164+
// Set Entry Mode
165+
m_entry = data;
166+
busy(attotime::from_usec(40));
167+
168+
} else if(data & 0x02) {
169+
// Cursor home
170+
m_ddac = 0;
171+
m_shift = 0;
172+
m_access_ddram = true;
173+
busy(attotime::from_usec(16400));
174+
175+
} else if(data & 0x01) {
176+
// Display clear
177+
memset(m_ddram, 0x20, sizeof(m_ddram));
178+
m_ddac = 0x00;
179+
m_entry |= 0x02;
180+
busy(attotime::from_usec(16400));
181+
}
182+
}
183+
184+
u8 lc7985_device::status_r()
185+
{
186+
return (m_access_ddram ? m_ddac : m_cgac) | (m_busy_flag ? 0x80 : 0x00);
187+
}
188+
189+
void lc7985_device::dr_w(u8 data)
190+
{
191+
if(m_access_ddram) {
192+
m_ddram[(m_function & 0x08) && m_ddac >= 64 ? m_ddac - (64-40) : m_ddac] = data;
193+
switch(m_entry & 0x03) {
194+
case 0: dec_ddac(); break;
195+
case 1: dec_ddac(); shift_right(); break;
196+
case 2: inc_ddac(); break;
197+
case 3: inc_ddac(); shift_left(); break;
198+
}
199+
200+
} else {
201+
m_cgram[m_cgac] = data;
202+
if(m_entry & 0x02)
203+
m_cgac = (m_cgac + 1) & 0x3f;
204+
else
205+
m_cgac = (m_cgac - 1) & 0x3f;
206+
}
207+
}
208+
209+
u8 lc7985_device::dr_r()
210+
{
211+
u8 res;
212+
if(m_access_ddram) {
213+
res = m_ddram[(m_function & 0x08) && m_ddac >= 64 ? m_ddac - (64-40) : m_ddac];
214+
if(m_entry & 0x02)
215+
inc_ddac();
216+
else
217+
dec_ddac();
218+
219+
} else {
220+
res = m_cgram[m_cgac];
221+
if(m_entry & 0x02)
222+
m_cgac = (m_cgac + 1) & 0x3f;
223+
else
224+
m_cgac = (m_cgac - 1) & 0x3f;
225+
}
226+
return res;
227+
}
228+
229+
const u8 *lc7985_device::render()
230+
{
231+
memset(m_render_buffer, 0, sizeof(m_render_buffer));
232+
if(!(m_display & 0x04))
233+
return m_render_buffer;
234+
235+
if(m_function & 0x08) {
236+
for(int y = 0; y != 2; y++) {
237+
for(int x = 0; x != 40; x ++) {
238+
u8 c = m_ddram[((x + 80 - m_shift) % 40) + 40*y];
239+
const u8 *src = c < 32 ? m_cgram + 8*(c & 7) : m_cgrom + 16 * c;
240+
u8 *dest = m_render_buffer + 8 * y + 16 * x;
241+
for(int z = 0; z != 8; z ++)
242+
*dest++ = *src++ & 0x1f;
243+
}
244+
}
245+
if(m_display & 0x03) {
246+
int cx = ((m_ddac & 0x3f) + 80 - m_shift) % 80;
247+
u8 *dest = m_render_buffer + (m_ddac >= 0x40 ? 8 : 0) + 16*cx;
248+
if(m_display & 0x02)
249+
dest[7] = 0x1f;
250+
if(m_display & 0x01) {
251+
bool on = int(machine().time().as_double() / 0.409) & 1;
252+
if(on)
253+
for(int z = 0; z != 8; z ++)
254+
*dest++ = 0x1f;
255+
}
256+
}
257+
258+
} else if(m_function & 0x04) {
259+
for(int x = 0; x != 80; x ++) {
260+
u8 c = m_ddram[(x + 80 - m_shift) % 80];
261+
const u8 *src = c < 32 ? m_cgram + 8*(c & 6) : m_cgrom + 16 * c;
262+
u8 *dest = m_render_buffer + 16 * x;
263+
for(int z = 0; z != 11; z ++)
264+
*dest++ = *src++ & 0x1f;
265+
}
266+
if(m_display & 0x03) {
267+
int cx = (m_ddac + 80 - m_shift) % 80;
268+
u8 *dest = m_render_buffer + 16*cx;
269+
if(m_display & 0x02)
270+
dest[10] = 0x1f;
271+
if(m_display & 0x01) {
272+
bool on = int(machine().time().as_double() / 0.409) & 1;
273+
if(on)
274+
for(int z = 0; z != 11; z ++)
275+
*dest++ = 0x1f;
276+
}
277+
}
278+
279+
} else {
280+
for(int x = 0; x != 80; x ++) {
281+
u8 c = m_ddram[(x + 80 - m_shift) % 80];
282+
const u8 *src = c < 32 ? m_cgram + 8*(c & 7) : m_cgrom + 16 * c;
283+
u8 *dest = m_render_buffer + 16 * x;
284+
for(int z = 0; z != 8; z ++)
285+
*dest++ = *src++ & 0x1f;
286+
}
287+
if(m_display & 0x03) {
288+
int cx = (m_ddac + 80 - m_shift) % 80;
289+
u8 *dest = m_render_buffer + 16*cx;
290+
if(m_display & 0x02)
291+
dest[7] = 0x1f;
292+
if(m_display & 0x01) {
293+
bool on = int(machine().time().as_double() / 0.409) & 1;
294+
if(on)
295+
for(int z = 0; z != 8; z ++)
296+
*dest++ = 0x1f;
297+
}
298+
}
299+
}
300+
return m_render_buffer;
301+
}
302+

src/devices/video/lc7985.h

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
// license:BSD-3-Clause
2+
// copyright-holders:Olivier Galibert
3+
/***************************************************************************
4+
5+
Sanyo LC7985NA/LC7985ND LCD controller
6+
7+
***************************************************************************/
8+
9+
#ifndef MAME_VIDEO_LC7985_H
10+
#define MAME_VIDEO_LC7985_H
11+
12+
#pragma once
13+
14+
class lc7985_device : public device_t
15+
{
16+
public:
17+
lc7985_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
18+
19+
void ir_w(u8 data);
20+
u8 status_r();
21+
void dr_w(u8 data);
22+
u8 dr_r();
23+
24+
// 5 bits used per byte, blocks of 16 lines, 80 blocks
25+
const u8 *render();
26+
27+
protected:
28+
virtual void device_start() override;
29+
virtual void device_reset() override;
30+
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
31+
virtual const tiny_rom_entry *device_rom_region() const override;
32+
33+
private:
34+
optional_region_ptr<u8> m_cgrom_region; // internal chargen ROM
35+
u8 m_render_buffer[16*40];
36+
u8 m_ddram[80];
37+
u8 m_cgram[64];
38+
const u8 *m_cgrom;
39+
emu_timer *m_busy_timer;
40+
u8 m_ddac;
41+
u8 m_cgac;
42+
u8 m_shift;
43+
u8 m_function;
44+
u8 m_cds;
45+
u8 m_display;
46+
u8 m_entry;
47+
48+
bool m_busy_flag;
49+
bool m_access_ddram;
50+
51+
void inc_ddac();
52+
void dec_ddac();
53+
void shift_left();
54+
void shift_right();
55+
56+
void busy(attotime tm);
57+
};
58+
59+
DECLARE_DEVICE_TYPE(LC7985, lc7985_device)
60+
61+
#endif // MAME_VIDEO_LC7985_H

0 commit comments

Comments
 (0)