1 // license:BSD-3-Clause
2 // copyright-holders:Sandro Ronco
3 /***************************************************************************
4 
5         SED1520 LCD controller
6 
7         TODO:
8         - busy flag
9 
10 ***************************************************************************/
11 
12 #include "emu.h"
13 #include "video/sed1520.h"
14 
15 #include "screen.h"
16 
17 
18 //**************************************************************************
19 //  DEVICE DEFINITIONS
20 //**************************************************************************
21 
22 DEFINE_DEVICE_TYPE(SED1520, sed1520_device, "sed1520", "Epson SED1520")
23 
24 
25 //**************************************************************************
26 //  live device
27 //**************************************************************************
28 
29 //-------------------------------------------------
30 //  sed1520_device - constructor
31 //-------------------------------------------------
32 
sed1520_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)33 sed1520_device::sed1520_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
34 	device_t(mconfig, SED1520, tag, owner, clock), m_lcd_on(0), m_busy(0), m_page(0), m_column(0), m_old_column(0), m_start_line(0),
35 	m_adc(0), m_static_drive(0), m_modify_write(false),
36 	m_screen_update_cb(*this)
37 {
38 }
39 
40 
41 //-------------------------------------------------
42 //  device_start - device-specific startup
43 //-------------------------------------------------
44 
device_start()45 void sed1520_device::device_start()
46 {
47 	m_screen_update_cb.resolve();
48 
49 	// state saving
50 	save_item(NAME(m_lcd_on));
51 	save_item(NAME(m_busy));
52 	save_item(NAME(m_page));
53 	save_item(NAME(m_column));
54 	save_item(NAME(m_old_column));
55 	save_item(NAME(m_start_line));
56 	save_item(NAME(m_adc));
57 	save_item(NAME(m_static_drive));
58 	save_item(NAME(m_modify_write));
59 	save_item(NAME(m_vram));
60 }
61 
62 //-------------------------------------------------
63 //  device_reset - device-specific reset
64 //-------------------------------------------------
65 
device_reset()66 void sed1520_device::device_reset()
67 {
68 	m_lcd_on = 0;
69 	m_busy = 0;
70 	m_page = 3;
71 	m_column = 0;
72 	m_old_column = 0;
73 	m_start_line = 0;
74 	m_adc = 1;
75 	m_static_drive = 0;
76 	m_modify_write = false;
77 	memset(m_vram, 0x00, sizeof(m_vram));
78 }
79 
80 
81 //**************************************************************************
82 //  device interface
83 //**************************************************************************
84 
screen_update(screen_device & screen,bitmap_ind16 & bitmap,const rectangle & cliprect)85 uint32_t sed1520_device::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
86 {
87 	if (m_lcd_on)
88 	{
89 		if (!m_screen_update_cb.isnull())
90 			m_screen_update_cb(bitmap, cliprect, m_vram, m_start_line, m_adc);
91 	}
92 	else if (m_static_drive)
93 		return UPDATE_HAS_NOT_CHANGED;
94 	else
95 		bitmap.fill(0, cliprect);
96 
97 	return 0;
98 }
99 
read(offs_t offset)100 uint8_t sed1520_device::read(offs_t offset)
101 {
102 	if (offset & 0x01)
103 		return data_read();
104 	else
105 		return status_read();
106 }
107 
write(offs_t offset,uint8_t data)108 void sed1520_device::write(offs_t offset, uint8_t data)
109 {
110 	if (offset & 0x01)
111 		data_write(data);
112 	else
113 		control_write(data);
114 }
115 
control_write(uint8_t data)116 void sed1520_device::control_write(uint8_t data)
117 {
118 	if((data & 0xfe) == 0xae)            // display on/off
119 		m_lcd_on = data & 0x01;
120 	else if((data & 0xe0) == 0xc0)       // set start line
121 		m_start_line = data & 0x1f;
122 	else if((data & 0xfc) == 0xb8)       // set page address
123 		m_page = data & 0x03;
124 	else if((data & 0x80) == 0x00)       // set column address
125 		m_column = data % 80;
126 	else if((data & 0xfe) == 0xa0)       // select ADC
127 		m_adc = data & 0x01;
128 	else if((data & 0xfe) == 0xa4)       // static drive on/off
129 		m_static_drive = data & 0x01;
130 	else if((data & 0xfe) == 0xa8)       // select duty
131 		;
132 	else if(data == 0xe0)                // read-modify-write on
133 	{
134 		m_modify_write = true;
135 		m_old_column = m_column;
136 	}
137 	else if(data == 0xee)                // read-modify-write off
138 	{
139 		m_modify_write = false;
140 		m_column = m_old_column;
141 	}
142 	else if(data == 0xe2)                // reset
143 	{
144 		m_start_line = m_column = 0;
145 		m_page = 3;
146 	}
147 	else
148 		logerror("%s: invalid SED1520 command: %x\n", tag(), data);
149 }
150 
status_read()151 uint8_t sed1520_device::status_read()
152 {
153 	uint8_t data = (m_busy << 7) | (m_adc << 6) | (m_lcd_on << 5);
154 	return data;
155 }
156 
data_write(uint8_t data)157 void sed1520_device::data_write(uint8_t data)
158 {
159 	m_vram[(m_page * 80 + m_column) % sizeof(m_vram)] = data;
160 	m_column = (m_column + 1) % 80;
161 }
162 
data_read()163 uint8_t sed1520_device::data_read()
164 {
165 	uint8_t data = m_vram[(m_page * 80 + m_column) % sizeof(m_vram)];
166 	if (!m_modify_write)
167 		m_column = (m_column + 1) % 80;
168 	return data;
169 }
170