diff options
Diffstat (limited to 'src/devices/bus/centronics/epson_lx810l.c')
-rw-r--r-- | src/devices/bus/centronics/epson_lx810l.c | 632 |
1 files changed, 632 insertions, 0 deletions
diff --git a/src/devices/bus/centronics/epson_lx810l.c b/src/devices/bus/centronics/epson_lx810l.c new file mode 100644 index 00000000000..eed6401875f --- /dev/null +++ b/src/devices/bus/centronics/epson_lx810l.c @@ -0,0 +1,632 @@ +// license:BSD-3-Clause +// copyright-holders:Ramiro Polla, Felipe Sanches +/* + * Epson LX-810L dot matrix printer emulation + + * IC list: + * uPD7810HG (cpu) + * E05A30 (gate array) + * 2064C (8k RAM) + * ER59256 (EEP-ROM - serial nvram) + * SLA7020M (step motor driver) + * uPC494C (pulse width modulation control) + * + * Devices boot and enter main input loop. Data is received through the + * centronics bus and printed as expected. The actual paper output is + * still not implemented, though. Look at the output from the fire signal + * (epson_lx810l_t::co0_w()) to see what's actually being printed. + * + * It is possible to run the printers' self test with this procedure: + * - Turn on device; + * - Toggle Line Feed button (press 'L'); + * - Reset device; + * - Toggle Line Feed button again; + * - Press Online button (press 'O'); + * - Press Online button again; + * + * The printer's carriage will seek home, it will pull in paper for a while, + * and it will start printing some test data. The Online LED will blink at + * each line. Look at the output from the fire signal to see what's actually + * being printed (epson_lx810l_t::co0_w()). + */ + +#include "epson_lx810l.h" +extern const char layout_lx800[]; /* use layout from lx800 */ + +//#define LX810LDEBUG +#ifdef LX810LDEBUG +#define LX810LLOG(...) fprintf(stderr, __VA_ARGS__) +#else +#define LX810LLOG(...) +#endif + +//************************************************************************** +// DEVICE DEFINITIONS +//************************************************************************** + +const device_type EPSON_LX810L = &device_creator<epson_lx810l_t>; +const device_type EPSON_AP2000 = &device_creator<epson_ap2000_t>; + + +//------------------------------------------------- +// ROM( lx810l ) +//------------------------------------------------- + +ROM_START( lx810l ) + ROM_REGION(0x8000, "maincpu", 0) + ROM_LOAD("lx810l.ic3c", 0x0000, 0x8000, CRC(a66454e1) SHA1(8e6f2f98abcbd8af6e34b9ba746edf0d18aef843) ) + ROM_REGION(0x20, "eeprom", 0) + ROM_LOAD( "at93c06", 0x00, 0x20, NO_DUMP ) +ROM_END + + +//------------------------------------------------- +// ROM( ap2000 ) +//------------------------------------------------- + +ROM_START( ap2000 ) + ROM_REGION(0x8000, "maincpu", 0) + ROM_LOAD("ap2k.ic3c", 0x0000, 0x8000, CRC(ee7294b7) SHA1(219ffa6ff661ce95d5772c9fc1967093718f04e9) ) + ROM_REGION(0x20, "eeprom", 0) + ROM_LOAD( "at93c06", 0x00, 0x20, NO_DUMP ) +ROM_END + + +//------------------------------------------------- +// rom_region - device-specific ROM region +//------------------------------------------------- + +const rom_entry *epson_lx810l_t::device_rom_region() const +{ + return ROM_NAME( lx810l ); +} + + +//------------------------------------------------- +// rom_region - device-specific ROM region +//------------------------------------------------- + +const rom_entry *epson_ap2000_t::device_rom_region() const +{ + return ROM_NAME( ap2000 ); +} + + +//------------------------------------------------- +// ADDRESS_MAP( lx810l_mem ) +//------------------------------------------------- + +static ADDRESS_MAP_START( lx810l_mem, AS_PROGRAM, 8, epson_lx810l_t ) + AM_RANGE(0x0000, 0x7fff) AM_ROM /* 32k firmware */ + AM_RANGE(0x8000, 0x9fff) AM_RAM /* 8k external RAM */ + AM_RANGE(0xa000, 0xbfff) AM_READWRITE(fakemem_r, fakemem_w) /* fake memory, write one, set all */ + AM_RANGE(0xc000, 0xdfff) AM_MIRROR(0x1ff0) AM_DEVREADWRITE("e05a30", e05a30_device, read, write) + AM_RANGE(0xe000, 0xfeff) AM_NOP /* not used */ + AM_RANGE(0xff00, 0xffff) AM_RAM /* internal CPU RAM */ +ADDRESS_MAP_END + + +//------------------------------------------------- +// ADDRESS_MAP( lx810l_io ) +//------------------------------------------------- + +static ADDRESS_MAP_START( lx810l_io, AS_IO, 8, epson_lx810l_t ) + AM_RANGE(UPD7810_PORTA, UPD7810_PORTA) AM_READWRITE(porta_r, porta_w) + AM_RANGE(UPD7810_PORTB, UPD7810_PORTB) AM_READWRITE(portb_r, portb_w) + AM_RANGE(UPD7810_PORTC, UPD7810_PORTC) AM_READWRITE(portc_r, portc_w) +ADDRESS_MAP_END + + +//------------------------------------------------- +// MACHINE_DRIVER( epson_lx810l ) +//------------------------------------------------- + +static MACHINE_CONFIG_FRAGMENT( epson_lx810l ) + /* basic machine hardware */ + MCFG_CPU_ADD("maincpu", UPD7810, XTAL_14_7456MHz) + MCFG_CPU_PROGRAM_MAP(lx810l_mem) + MCFG_CPU_IO_MAP(lx810l_io) + MCFG_UPD7810_AN0(READ8(epson_lx810l_t, an0_r)) + MCFG_UPD7810_AN1(READ8(epson_lx810l_t, an1_r)) + MCFG_UPD7810_AN2(READ8(epson_lx810l_t, an2_r)) + MCFG_UPD7810_AN3(READ8(epson_lx810l_t, an3_r)) + MCFG_UPD7810_AN4(READ8(epson_lx810l_t, an4_r)) + MCFG_UPD7810_AN5(READ8(epson_lx810l_t, an5_r)) + MCFG_UPD7810_AN6(READ8(epson_lx810l_t, an6_r)) + MCFG_UPD7810_AN7(READ8(epson_lx810l_t, an7_r)) + MCFG_UPD7810_CO0(WRITELINE(epson_lx810l_t, co0_w)) + MCFG_UPD7810_CO1(WRITELINE(epson_lx810l_t, co1_w)) + + MCFG_DEFAULT_LAYOUT(layout_lx800) + + /* audio hardware */ + MCFG_SPEAKER_STANDARD_MONO("mono") + MCFG_SOUND_ADD("speaker", SPEAKER_SOUND, 0) + MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25) + + /* gate array */ + MCFG_DEVICE_ADD("e05a30", E05A30, 0) + MCFG_E05A30_PRINTHEAD_CALLBACK(WRITE16(epson_lx810l_t, printhead)) + MCFG_E05A30_PF_STEPPER_CALLBACK(WRITE8(epson_lx810l_t, pf_stepper)) + MCFG_E05A30_CR_STEPPER_CALLBACK(WRITE8(epson_lx810l_t, cr_stepper)) + MCFG_E05A30_READY_CALLBACK(WRITELINE(epson_lx810l_t, e05a30_ready)) + MCFG_E05A30_CENTRONICS_ACK_CALLBACK(WRITELINE(epson_lx810l_t, e05a30_centronics_ack)) + MCFG_E05A30_CENTRONICS_BUSY_CALLBACK(WRITELINE(epson_lx810l_t, e05a30_centronics_busy)) + MCFG_E05A30_CENTRONICS_PERROR_CALLBACK(WRITELINE(epson_lx810l_t, e05a30_centronics_perror)) + MCFG_E05A30_CENTRONICS_FAULT_CALLBACK(WRITELINE(epson_lx810l_t, e05a30_centronics_fault)) + MCFG_E05A30_CENTRONICS_SELECT_CALLBACK(WRITELINE(epson_lx810l_t, e05a30_centronics_select)) + + /* 256-bit eeprom */ + MCFG_EEPROM_SERIAL_93C06_ADD("eeprom") + + /* steppers */ + //should this have MCFG_STEPPER_MAX_STEPS(200*2) ? code shows 200 steps... + MCFG_STEPPER_ADD("pf_stepper") + MCFG_STEPPER_REEL_TYPE(NOT_A_REEL) + MCFG_STEPPER_START_INDEX(16) + MCFG_STEPPER_END_INDEX(24) + MCFG_STEPPER_INDEX_PATTERN(0x00) + MCFG_STEPPER_INIT_PHASE(0) + + MCFG_STEPPER_ADD("cr_stepper") + MCFG_STEPPER_REEL_TYPE(NOT_A_REEL) + MCFG_STEPPER_START_INDEX(16) + MCFG_STEPPER_END_INDEX(24) + MCFG_STEPPER_INDEX_PATTERN(0x00) + MCFG_STEPPER_INIT_PHASE(2) + +MACHINE_CONFIG_END + +//------------------------------------------------- +// machine_config_additions - device-specific +// machine configurations +//------------------------------------------------- + +machine_config_constructor epson_lx810l_t::device_mconfig_additions() const +{ + return MACHINE_CONFIG_NAME( epson_lx810l ); +} + + +/*************************************************************************** + INPUT PORTS +***************************************************************************/ + +static INPUT_PORTS_START( epson_lx810l ) + + /* Buttons on printer */ + PORT_START("ONLINE") + PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("On Line") PORT_CODE(KEYCODE_O) PORT_CHANGED_MEMBER(DEVICE_SELF, epson_lx810l_t, online_sw, NULL) + PORT_START("FORMFEED") + PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Form Feed") PORT_CODE(KEYCODE_F) PORT_TOGGLE + PORT_START("LINEFEED") + PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Line Feed") PORT_CODE(KEYCODE_L) PORT_TOGGLE + PORT_START("LOADEJECT") + PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Load/Eject") PORT_CODE(KEYCODE_E) + + /* DIPSW1 */ + PORT_START("DIPSW1") + + PORT_DIPNAME(0x01, 0x01, "Character spacing") + PORT_DIPLOCATION("DIP:1") + PORT_DIPSETTING(0x01, "12 cpi") /* default */ + PORT_DIPSETTING(0x00, "10 cpi") + + PORT_DIPNAME(0x02, 0x00, "Shape of zero") + PORT_DIPLOCATION("DIP:2") + PORT_DIPSETTING(0x02, "Slashed") + PORT_DIPSETTING(0x00, "Not slashed") /* default */ + + PORT_DIPNAME(0x0c, 0x08, "Page length") + PORT_DIPLOCATION("DIP:3,4") + PORT_DIPSETTING(0x00, "11 inches") + PORT_DIPSETTING(0x04, "12 inches") + PORT_DIPSETTING(0x08, "8.5 inches") /* default */ + PORT_DIPSETTING(0x0c, "11.7 inches") + + PORT_DIPNAME(0x10, 0x10, "Character table") + PORT_DIPLOCATION("DIP:5") + PORT_DIPSETTING(0x10, "Graphics") /* default */ + PORT_DIPSETTING(0x00, "Italics") + + PORT_DIPNAME(0xe0, 0xe0, "International characters and PC selection") + PORT_DIPLOCATION("DIP:6,7,8") + PORT_DIPSETTING(0xe0, "United States") /* default */ + PORT_DIPSETTING(0x60, "France") + PORT_DIPSETTING(0xa0, "Germany") + PORT_DIPSETTING(0x20, "United Kingdom") + PORT_DIPSETTING(0xc0, "Denmark") + PORT_DIPSETTING(0x40, "Sweden") + PORT_DIPSETTING(0x80, "Italy") + PORT_DIPSETTING(0x00, "Spain") + + /* DIPSW2 */ + PORT_START("DIPSW2") + + PORT_DIPNAME(0x01, 0x01, "Short tear-off") + PORT_DIPLOCATION("DIP:1") + PORT_DIPSETTING(0x01, "Invalid") /* default */ + PORT_DIPSETTING(0x00, "Valid") + + PORT_DIPNAME(0x02, 0x00, "Cut-sheet feeder mode") + PORT_DIPLOCATION("DIP:2") + PORT_DIPSETTING(0x02, "ON") + PORT_DIPSETTING(0x00, "OFF") /* default */ + + PORT_DIPNAME(0x04, 0x00, "Skip-over-perforation") + PORT_DIPLOCATION("DIP:3") + PORT_DIPSETTING(0x04, "ON") + PORT_DIPSETTING(0x00, "OFF") /* default */ + + PORT_DIPNAME(0x08, 0x00, "Auto line feed") + PORT_DIPLOCATION("DIP:4") + PORT_DIPSETTING(0x08, "ON") + PORT_DIPSETTING(0x00, "OFF") /* default */ + +INPUT_PORTS_END + + +//------------------------------------------------- +// input_ports - device-specific input ports +//------------------------------------------------- + +ioport_constructor epson_lx810l_t::device_input_ports() const +{ + return INPUT_PORTS_NAME( epson_lx810l ); +} + +INPUT_CHANGED_MEMBER(epson_lx810l_t::online_sw) +{ + m_maincpu->set_input_line(UPD7810_INTF2, newval ? CLEAR_LINE : ASSERT_LINE); +} + + +//************************************************************************** +// LIVE DEVICE +//************************************************************************** + +//------------------------------------------------- +// epson_lx810l_t - constructor +//------------------------------------------------- + +epson_lx810l_t::epson_lx810l_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : + device_t(mconfig, EPSON_LX810L, "Epson LX-810L", tag, owner, clock, "lx810l", __FILE__), + device_centronics_peripheral_interface(mconfig, *this), + m_maincpu(*this, "maincpu"), + m_pf_stepper(*this, "pf_stepper"), + m_cr_stepper(*this, "cr_stepper"), + m_eeprom(*this, "eeprom"), + m_speaker(*this, "speaker"), + m_e05a30(*this, "e05a30"), + m_93c06_clk(0), + m_93c06_cs(0), + m_printhead(0), + m_pf_pos_abs(200), + m_cr_pos_abs(200), + m_real_cr_pos(200), + m_real_cr_steps(0), + m_real_cr_dir(0) +{ +} + +epson_lx810l_t::epson_lx810l_t(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source) : + device_t(mconfig, type, name, tag, owner, clock, shortname, __FILE__), + device_centronics_peripheral_interface(mconfig, *this), + m_maincpu(*this, "maincpu"), + m_pf_stepper(*this, "pf_stepper"), + m_cr_stepper(*this, "cr_stepper"), + m_eeprom(*this, "eeprom"), + m_speaker(*this, "speaker"), + m_e05a30(*this, "e05a30"), + m_93c06_clk(0), + m_93c06_cs(0), + m_printhead(0), + m_pf_pos_abs(200), + m_cr_pos_abs(200), + m_real_cr_pos(200), + m_real_cr_steps(0), + m_real_cr_dir(0) +{ +} + +epson_ap2000_t::epson_ap2000_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : epson_lx810l_t(mconfig, EPSON_AP2000, "Epson ActionPrinter 2000", tag, owner, clock, "ap2000", __FILE__) +{ } + + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + + + + +void epson_lx810l_t::device_start() +{ +} + + +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- + +void epson_lx810l_t::device_reset() +{ + m_speaker->level_w(0); +} + + +//------------------------------------------------- +// device_timer - device-specific timer +//------------------------------------------------- + +void epson_lx810l_t::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) +{ + switch (id) { + case TIMER_CR: + /* The firmware issues two half-steps in sequence, one immediately + * after the other. At full speed, the motor does two half-steps at + * each 833 microseconds. A timer fires the printhead twice, with + * the same period as each half-step (417 microseconds), but with + * a 356 microseconds delay relative to the motor steps. + */ + m_real_cr_pos += param; + m_real_cr_steps--; + if (m_real_cr_steps) + timer_set(attotime::from_usec(400), TIMER_CR, m_real_cr_dir); + break; + } +} + + +/*************************************************************************** + FAKEMEM READ/WRITE +***************************************************************************/ + +READ8_MEMBER(epson_lx810l_t::fakemem_r) +{ + return m_fakemem; +} + +WRITE8_MEMBER(epson_lx810l_t::fakemem_w) +{ + m_fakemem = data; +} + + +/*************************************************************************** + I/O PORTS +***************************************************************************/ + +/* + * PA0 R CN7 sensor (Home Position, HP, active low) + * PA1 R CN6 sensor (Paper-End, PE, active low) + * PA2 R CN4 sensor (Release, low = tractor) + * PA3 W Stepper motor voltage reference (these 3 pins make up one voltage) + * PA4 W Stepper motor voltage reference (these 3 pins make up one voltage) + * PA5 W Stepper motor voltage reference (these 3 pins make up one voltage) + * PA6 R Line Feed SWITCH + * PA7 R Form Feed SWITCH + */ +READ8_MEMBER( epson_lx810l_t::porta_r ) +{ + UINT8 result = 0; + UINT8 hp_sensor = m_cr_pos_abs <= 0 ? 0 : 1; + UINT8 pe_sensor = m_pf_pos_abs <= 0 ? 1 : 0; + + result |= hp_sensor; /* home position */ + result |= pe_sensor << 1; /* paper end */ + result |= ioport("LINEFEED")->read() << 6; + result |= ioport("FORMFEED")->read() << 7; + + LX810LLOG("%s: lx810l_PA_r(%02x): result %02x\n", machine().describe_context(), offset, result); + + return result; +} + +WRITE8_MEMBER( epson_lx810l_t::porta_w ) +{ + LX810LLOG("%s: lx810l_PA_w(%02x): %02x: stepper vref %d\n", machine().describe_context(), offset, data, BIT(data, 3) | (BIT(data, 4)<<1) | (BIT(data, 5)<<2)); +} + +/* + * PB0 R DIP1.0 & 93C06.DO + * PB1 RW DIP1.1 & 93C06.DI + * PB2 R DIP1.2 + * PB3 R DIP1.3 + * PB4 R DIP1.4 + * PB5 R DIP1.5 + * PB6 R DIP1.6 + * PB7 R DIP1.7 + */ +READ8_MEMBER( epson_lx810l_t::portb_r ) +{ + UINT8 result = ~ioport("DIPSW1")->read(); + + /* if 93C06 is selected */ + if (m_93c06_cs) { + UINT8 do_r = m_eeprom->do_read(); + result &= 0xfe; + result |= do_r; + } + + LX810LLOG("%s: lx810l_PB_r(%02x): result %02x\n", machine().describe_context(), offset, result); + + return result; +} + +WRITE8_MEMBER( epson_lx810l_t::portb_w ) +{ + UINT8 data_in = BIT(data, 1); + + /* if 93C06 is selected */ + if (m_93c06_cs) + m_eeprom->di_write(data_in); + + LX810LLOG("%s: lx810l_PB_w(%02x): %02x: 93c06 data %d\n", machine().describe_context(), offset, data, data_in); +} + +/* + * PC0 W TXD serial i/o txd, also TAMA.25 + * PC1 R RXD serial i/o rxd, also E05A30.28 + * PC2 W ONLINE LP online led + * PC3 R ONLINE SW online switch + * PC4 W 93C06.SK + * PC5 W 93C06.CS + * PC6 W FIRE drive pulse width signal, also E05A30.57 + * PC7 W BUZZER buzzer signal + */ +READ8_MEMBER( epson_lx810l_t::portc_r ) +{ + UINT8 result = 0; + + /* result |= ioport("serial")->read() << 1; */ + result |= !ioport("ONLINE")->read() << 3; + result |= m_93c06_clk << 4; + result |= m_93c06_cs << 5; + + LX810LLOG("%s: lx810l_PC_r(%02x): %02x\n", machine().describe_context(), offset, result); + + return result; +} + +WRITE8_MEMBER( epson_lx810l_t::portc_w ) +{ + /* ioport("serial")->write(BIT(data, 0)); */ + + m_93c06_clk = BIT(data, 4); + m_93c06_cs = !BIT(data, 5); + + LX810LLOG("%s: PC_w(%02x): %02x 93c06 clk: %d cs: %d\n", machine().describe_context(), offset, data, m_93c06_clk, m_93c06_cs); + + m_eeprom->clk_write(m_93c06_clk ? ASSERT_LINE : CLEAR_LINE); + m_eeprom->cs_write (m_93c06_cs ? ASSERT_LINE : CLEAR_LINE); + + output_set_value("online_led", !BIT(data, 2)); +} + + +/*************************************************************************** + GATE ARRAY +***************************************************************************/ + +WRITE16_MEMBER( epson_lx810l_t::printhead ) +{ + m_printhead = data; +} + +WRITE8_MEMBER( epson_lx810l_t::pf_stepper ) +{ + m_pf_stepper->update(data); + m_pf_pos_abs = 200 - m_pf_stepper->get_absolute_position(); + + LX810LLOG("%s: %s(%02x); abs %d\n", machine().describe_context(), __func__, data, m_pf_pos_abs); +} + +WRITE8_MEMBER( epson_lx810l_t::cr_stepper ) +{ + int m_cr_pos_abs_prev = m_cr_pos_abs; + + m_cr_stepper->update(data); + m_cr_pos_abs = 200 - m_cr_stepper->get_absolute_position(); + + if (m_cr_pos_abs > m_cr_pos_abs_prev) { + /* going right */ + m_real_cr_dir = 1; + } else { + /* going left */ + m_real_cr_dir = -1; + } + + if (!m_real_cr_steps) + timer_set(attotime::from_usec(400), TIMER_CR, m_real_cr_dir); + m_real_cr_steps++; + + LX810LLOG("%s: %s(%02x); abs %d\n", machine().describe_context(), __func__, data, m_cr_pos_abs); +} + +WRITE_LINE_MEMBER( epson_lx810l_t::e05a30_ready ) +{ + m_maincpu->set_input_line(INPUT_LINE_NMI, PULSE_LINE); +} + + +/*************************************************************************** + Extended Timer Output +***************************************************************************/ + +WRITE_LINE_MEMBER( epson_lx810l_t::co0_w ) +{ + /* TODO Draw the dots on the paper using this information. */ + + /* Printhead is being fired on !state. */ + if (!state) { + /* The firmware expects a 300 microseconds delay between the fire + * signal and the impact of the printhead on the paper. This can be + * verified by the timings of the steps and fire signals for the + * same positions with different directions (left to right or right + * to left). We don't simulate this delay since it is smaller than + * the time it takes the printhead to travel one pixel (which would + * be 417 microseconds), so it makes no difference to us. + * It is interesting to note that the vertical alignment between + * lines which are being printed in different directions is + * noticeably off in the 20+ years old printer used for testing =). + */ + LX810LLOG("FIRE0 %d %d %04x\n", m_pf_pos_abs, m_real_cr_pos, m_printhead); + } +} + +WRITE_LINE_MEMBER( epson_lx810l_t::co1_w ) +{ + m_speaker->level_w(state); +} + + +/*************************************************************************** + ADC +***************************************************************************/ + +READ8_MEMBER(epson_lx810l_t::an0_r) +{ + UINT8 res = !!(ioport("DIPSW2")->read() & 0x01); + return res - 1; /* DIPSW2.1 */ +} + +READ8_MEMBER(epson_lx810l_t::an1_r) +{ + UINT8 res = !!(ioport("DIPSW2")->read() & 0x02); + return res - 1; /* DIPSW2.2 */ +} + +READ8_MEMBER(epson_lx810l_t::an2_r) +{ + UINT8 res = !!(ioport("DIPSW2")->read() & 0x04); + return res - 1; /* DIPSW2.3 */ +} + +READ8_MEMBER(epson_lx810l_t::an3_r) +{ + UINT8 res = !!(ioport("DIPSW2")->read() & 0x08); + return res - 1; /* DIPSW2.4 */ +} + +READ8_MEMBER(epson_lx810l_t::an4_r) +{ + return 0xff; +} + +READ8_MEMBER(epson_lx810l_t::an5_r) +{ + return 0xCB; /* motor voltage, 0xcb = 24V */ +} + +READ8_MEMBER(epson_lx810l_t::an6_r) +{ + UINT8 res = !ioport("LOADEJECT")->read(); + return res - 1; +} + +READ8_MEMBER(epson_lx810l_t::an7_r) +{ + return 0xff; +} |