1 // license:BSD-3-Clause
2 // copyright-holders:Dirk Best
3 /**********************************************************************
4
5 Epson LX-800 dot matrix printer
6
7 Skeleton driver
8
9 - CPU type uPD7810HG
10 - CPU PORTD and PORTF are connected to the Gate Array
11 - processing gets stuck in a loop, and never gets to scan the
12 input buttons and switches.
13 - CPU disassembly doesn't seem to indicate conditional JR or RET.
14
15 **********************************************************************/
16
17 #include "emu.h"
18 #include "epson_lx800.h"
19 #include "speaker.h"
20 #include "lx800.lh"
21
22
23
24 //**************************************************************************
25 // DEVICE DEFINITIONS
26 //**************************************************************************
27
28 DEFINE_DEVICE_TYPE(EPSON_LX800, epson_lx800_device, "lx800", "Epson LX-800")
29
30
31 //-------------------------------------------------
32 // ROM( lx800 )
33 //-------------------------------------------------
34
ROM_START(lx800)35 ROM_START( lx800 )
36 ROM_REGION(0x8000, "maincpu", 0)
37 ROM_LOAD("lx800.ic3c", 0x0000, 0x8000, CRC(da06c45b) SHA1(9618c940dd10d5b43cd1edd5763b90e6447de667) )
38 ROM_END
39
40
41 //-------------------------------------------------
42 // rom_region - device-specific ROM region
43 //-------------------------------------------------
44
45 const tiny_rom_entry *epson_lx800_device::device_rom_region() const
46 {
47 return ROM_NAME( lx800 );
48 }
49
50
51 //-------------------------------------------------
52 // ADDRESS_MAP( lx800_mem )
53 //-------------------------------------------------
54
lx800_mem(address_map & map)55 void epson_lx800_device::lx800_mem(address_map &map)
56 {
57 map(0x0000, 0x7fff).rom(); /* 32k firmware */
58 map(0x8000, 0x9fff).ram(); /* 8k external RAM */
59 map(0xa000, 0xbfff).noprw(); /* not used */
60 map(0xc000, 0xc007).mirror(0x1ff8).rw("ic3b", FUNC(e05a03_device::read), FUNC(e05a03_device::write));
61 map(0xe000, 0xfeff).noprw(); /* not used */
62 }
63
64
65 //-------------------------------------------------
66 // device_add_mconfig - add device configuration
67 //-------------------------------------------------
68
device_add_mconfig(machine_config & config)69 void epson_lx800_device::device_add_mconfig(machine_config &config)
70 {
71 /* basic machine hardware */
72 upd7810_device &upd(UPD7810(config, m_maincpu, 14.7456_MHz_XTAL));
73 upd.set_addrmap(AS_PROGRAM, &epson_lx800_device::lx800_mem);
74 upd.pa_in_cb().set(FUNC(epson_lx800_device::porta_r));
75 upd.pa_out_cb().set(FUNC(epson_lx800_device::porta_w));
76 upd.pb_in_cb().set_ioport("DIPSW1");
77 upd.pc_in_cb().set(FUNC(epson_lx800_device::portc_r));
78 upd.pc_out_cb().set(FUNC(epson_lx800_device::portc_w));
79 upd.an0_func().set(FUNC(epson_lx800_device::an0_r));
80 upd.an1_func().set(FUNC(epson_lx800_device::an1_r));
81 upd.an2_func().set(FUNC(epson_lx800_device::an2_r));
82 upd.an3_func().set(FUNC(epson_lx800_device::an3_r));
83 upd.an4_func().set(FUNC(epson_lx800_device::an4_r));
84 upd.an5_func().set(FUNC(epson_lx800_device::an5_r));
85
86 config.set_default_layout(layout_lx800);
87
88 /* audio hardware */
89 SPEAKER(config, "mono").front_center();
90 BEEP(config, m_beep, 4000); // ?
91 m_beep->add_route(ALL_OUTPUTS, "mono", 0.05);
92
93 /* gate array */
94 e05a03_device &ic3b(E05A03(config, "ic3b", 0));
95 ic3b.pe_lp_wr_callback().set_output("paperout_led");
96 ic3b.reso_wr_callback().set(FUNC(epson_lx800_device::reset_w));
97 ic3b.pe_wr_callback().set(FUNC(epson_lx800_device::centronics_pe_w));
98 ic3b.data_rd_callback().set(FUNC(epson_lx800_device::centronics_data_r));
99 }
100
101
102 //-------------------------------------------------
103 // INPUT_PORTS( epson_lx800 )
104 //-------------------------------------------------
105
106 INPUT_PORTS_START( epson_lx800 )
107 PORT_START("ONLINE")
PORT_CODE(KEYCODE_O)108 PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("On Line") PORT_CODE(KEYCODE_O)
109
110 PORT_START("FORMFEED")
111 PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Form Feed") PORT_CODE(KEYCODE_F)
112
113 PORT_START("LINEFEED")
114 PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Line Feed") PORT_CODE(KEYCODE_L)
115
116 PORT_START("DIPSW1")
117 PORT_DIPNAME(0x01, 0x00, "Typeface")
118 PORT_DIPLOCATION("DIP:8")
119 PORT_DIPSETTING(0x01, "Condensed")
120 PORT_DIPSETTING(0x00, DEF_STR(Normal))
121 PORT_DIPNAME(0x02, 0x00, "ZERO font")
122 PORT_DIPLOCATION("DIP:7")
123 PORT_DIPSETTING(0x02, "0")
124 PORT_DIPSETTING(0x00, "0")
125 PORT_DIPNAME(0x04, 0x00, "Character Table")
126 PORT_DIPLOCATION("DIP:6")
127 PORT_DIPSETTING(0x04, "Graphic")
128 PORT_DIPSETTING(0x00, "Italic")
129 PORT_DIPNAME(0x08, 0x00, "Paper-out detection")
130 PORT_DIPLOCATION("DIP:5")
131 PORT_DIPSETTING(0x08, "Valid")
132 PORT_DIPSETTING(0x00, "Invalid")
133 PORT_DIPNAME(0x10, 0x00, "Printing quality")
134 PORT_DIPLOCATION("DIP:4")
135 PORT_DIPSETTING(0x10, "NLQ")
136 PORT_DIPSETTING(0x00, "Draft")
137 PORT_DIPNAME(0xe0, 0xe0, "International character set")
138 PORT_DIPLOCATION("DIP:3,2,1")
139 PORT_DIPSETTING(0xe0, "U.S.A.")
140 PORT_DIPSETTING(0x60, "France")
141 PORT_DIPSETTING(0xa0, "Germany")
142 PORT_DIPSETTING(0x20, "U.K.")
143 PORT_DIPSETTING(0xc0, "Denmark")
144 PORT_DIPSETTING(0x40, "Sweden")
145 PORT_DIPSETTING(0x80, "Italy")
146 PORT_DIPSETTING(0x00, "Spain")
147
148 PORT_START("DIPSW2")
149 PORT_DIPNAME(0x01, 0x00, "Page length")
150 PORT_DIPLOCATION("DIP:4")
151 PORT_DIPSETTING(0x01, "12\"")
152 PORT_DIPSETTING(0x00, "11\"")
153 PORT_DIPNAME(0x02, 0x00, "Cut sheet feeder mode")
154 PORT_DIPLOCATION("DIP:3")
155 PORT_DIPSETTING(0x02, "Valid")
156 PORT_DIPSETTING(0x00, "Invalid")
157 PORT_DIPNAME(0x04, 0x00, "1\" skip over perforation")
158 PORT_DIPLOCATION("DIP:2")
159 PORT_DIPSETTING(0x04, "Valid")
160 PORT_DIPSETTING(0x00, "Invalid")
161 PORT_DIPNAME(0x08, 0x00, "AUTO FEED XT control")
162 PORT_DIPLOCATION("DIP:1")
163 PORT_DIPSETTING(0x08, "Fix to LOW")
164 PORT_DIPSETTING(0x00, "Depends on external signal")
165 INPUT_PORTS_END
166
167
168 //-------------------------------------------------
169 // input_ports - device-specific input ports
170 //-------------------------------------------------
171
172 ioport_constructor epson_lx800_device::device_input_ports() const
173 {
174 return INPUT_PORTS_NAME( epson_lx800 );
175 }
176
177
178
179 //**************************************************************************
180 // LIVE DEVICE
181 //**************************************************************************
182
183 //-------------------------------------------------
184 // epson_lx800_device - constructor
185 //-------------------------------------------------
186
epson_lx800_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)187 epson_lx800_device::epson_lx800_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
188 epson_lx800_device(mconfig, EPSON_LX800, tag, owner, clock)
189 {
190 }
191
epson_lx800_device(const machine_config & mconfig,device_type type,const char * tag,device_t * owner,uint32_t clock)192 epson_lx800_device::epson_lx800_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
193 device_t(mconfig, type, tag, owner, clock),
194 device_centronics_peripheral_interface(mconfig, *this),
195 m_maincpu(*this, "maincpu"),
196 m_beep(*this, "beeper"),
197 m_online_led(*this, "online_led")
198 {
199 }
200
201
202 //-------------------------------------------------
203 // device_start - device-specific startup
204 //-------------------------------------------------
205
device_start()206 void epson_lx800_device::device_start()
207 {
208 m_online_led.resolve();
209 }
210
211
212 //-------------------------------------------------
213 // device_reset - device-specific reset
214 //-------------------------------------------------
215
device_reset()216 void epson_lx800_device::device_reset()
217 {
218 m_beep->set_state(0);
219 }
220
221
222 /***************************************************************************
223 I/O PORTS
224 ***************************************************************************/
225
226 /* PA0 W CRCOM carriage motor, 0 = holding voltage, 1 = drive voltage
227 * PA1 not used
228 * PA2 W PFCOM paper feed motor, 0 = holding voltage, 1 = drive voltage
229 * PA3 R LF SW line feed switch
230 * PA4 R FF SW form feed switch
231 * PA5 R PE SW paper end sensor, 0 = no paper, 1 = paper
232 * PA6 not used
233 * PA7 R P/S P/S signal from the optional interface
234 */
porta_r(offs_t offset)235 uint8_t epson_lx800_device::porta_r(offs_t offset)
236 {
237 uint8_t result = 0;
238
239 logerror("%s: lx800_porta_r(%02x)\n", machine().describe_context(), offset);
240
241 result |= ioport("LINEFEED")->read() << 3;
242 result |= ioport("FORMFEED")->read() << 4;
243 result |= 1 << 5;
244
245 result |= 1 << 7;
246
247 return result;
248 }
249
porta_w(offs_t offset,uint8_t data)250 void epson_lx800_device::porta_w(offs_t offset, uint8_t data)
251 {
252 logerror("%s: lx800_porta_w(%02x): %02x\n", machine().describe_context(), offset, data);
253 logerror("--> carriage: %d, paper feed: %d\n", BIT(data, 0), BIT(data, 2));
254 }
255
256 /* PC0 W TXD serial i/o txd
257 * PC1 R RXD serial i/o rxd
258 * PC2 W ONLINE LP online led
259 * PC3 R ONLINE SW online switch
260 * PC4 W ERR centronics error
261 * PC5 W ACK centronics acknowledge
262 * PC6 W FIRE drive pulse width signal
263 * PC7 W BUZZER buzzer signal
264 */
portc_r(offs_t offset)265 uint8_t epson_lx800_device::portc_r(offs_t offset)
266 {
267 uint8_t result = 0;
268
269 logerror("%s: lx800_portc_r(%02x)\n", machine().describe_context(), offset);
270
271 result |= ioport("ONLINE")->read() << 3;
272
273 return result;
274 }
275
portc_w(offs_t offset,uint8_t data)276 void epson_lx800_device::portc_w(offs_t offset, uint8_t data)
277 {
278 logerror("%s: lx800_portc_w(%02x): %02x\n", machine().describe_context(), offset, data);
279 logerror("--> err: %d, ack: %d, fire: %d, buzzer: %d\n", BIT(data, 4), BIT(data, 5), BIT(data, 6), BIT(data, 7));
280
281 m_online_led = !BIT(data, 2);
282 m_beep->set_state(!BIT(data, 7));
283 }
284
READ_LINE_MEMBER(epson_lx800_device::an0_r)285 READ_LINE_MEMBER( epson_lx800_device::an0_r )
286 {
287 return BIT(ioport("DIPSW2")->read(), 0);
288 }
289
READ_LINE_MEMBER(epson_lx800_device::an1_r)290 READ_LINE_MEMBER( epson_lx800_device::an1_r )
291 {
292 return BIT(ioport("DIPSW2")->read(), 1);
293 }
294
READ_LINE_MEMBER(epson_lx800_device::an2_r)295 READ_LINE_MEMBER( epson_lx800_device::an2_r )
296 {
297 return BIT(ioport("DIPSW2")->read(), 2);
298 }
299
READ_LINE_MEMBER(epson_lx800_device::an3_r)300 READ_LINE_MEMBER( epson_lx800_device::an3_r )
301 {
302 return BIT(ioport("DIPSW2")->read(), 3); // can also read an external line AUTO_FEED_XT
303 }
304
READ_LINE_MEMBER(epson_lx800_device::an4_r)305 READ_LINE_MEMBER( epson_lx800_device::an4_r )
306 {
307 return 0; // Printer select line (0=always selected)
308 }
309
READ_LINE_MEMBER(epson_lx800_device::an5_r)310 READ_LINE_MEMBER( epson_lx800_device::an5_r )
311 {
312 return 1; // Monitors 24v line, should return 4.08 volts
313 }
314
315
316 /***************************************************************************
317 GATE ARRAY
318 ***************************************************************************/
319
centronics_data_r()320 uint8_t epson_lx800_device::centronics_data_r()
321 {
322 logerror("centronics: data read\n");
323 return 0x55;
324 }
325
WRITE_LINE_MEMBER(epson_lx800_device::centronics_pe_w)326 WRITE_LINE_MEMBER( epson_lx800_device::centronics_pe_w )
327 {
328 logerror("centronics: pe = %d\n", state);
329 }
330
WRITE_LINE_MEMBER(epson_lx800_device::reset_w)331 WRITE_LINE_MEMBER( epson_lx800_device::reset_w )
332 {
333 logerror("cpu reset");
334 m_maincpu->reset();
335 }
336