diff options
author | Miodrag Milanović <mmicko@gmail.com> | 2014-11-20 15:36:56 +0100 |
---|---|---|
committer | Miodrag Milanović <mmicko@gmail.com> | 2014-11-20 15:36:56 +0100 |
commit | 90a9ea5210d19415c1be2264efd85f7785fbccd6 (patch) | |
tree | fe8c1e4009716873f9d0e5b08cdef444df0923d4 | |
parent | 819a7289d840f983deebf67495a486870684906f (diff) | |
parent | 32bfdf37522b29c15899b1e445044c8973787b34 (diff) |
Merge pull request #50 from ramiropolla/lx810l
Added working Epson LX-810L and Epson ActionPrinter2000 printers
-rw-r--r-- | src/emu/bus/bus.mak | 2 | ||||
-rw-r--r-- | src/emu/bus/centronics/ctronics.c | 1 | ||||
-rw-r--r-- | src/emu/bus/centronics/epson_lx800.c | 61 | ||||
-rw-r--r-- | src/emu/bus/centronics/epson_lx800.h | 28 | ||||
-rw-r--r-- | src/emu/bus/centronics/epson_lx810l.c | 587 | ||||
-rw-r--r-- | src/emu/bus/centronics/epson_lx810l.h | 117 | ||||
-rw-r--r-- | src/emu/machine/e05a30.c | 163 | ||||
-rw-r--r-- | src/emu/machine/e05a30.h | 71 | ||||
-rw-r--r-- | src/emu/machine/machine.mak | 18 | ||||
-rw-r--r-- | src/emu/machine/steppers.c (renamed from src/mame/machine/steppers.c) | 0 | ||||
-rw-r--r-- | src/emu/machine/steppers.h (renamed from src/mame/machine/steppers.h) | 0 | ||||
-rw-r--r-- | src/mame/mame.mak | 4 | ||||
-rw-r--r-- | src/mess/includes/amstrad.h | 1 | ||||
-rw-r--r-- | src/mess/mess.mak | 2 | ||||
-rw-r--r-- | src/targets/mess.lst | 1 |
15 files changed, 965 insertions, 91 deletions
diff --git a/src/emu/bus/bus.mak b/src/emu/bus/bus.mak index 77b9facce09..c9bf3b24006 100644 --- a/src/emu/bus/bus.mak +++ b/src/emu/bus/bus.mak @@ -956,10 +956,12 @@ BUSOBJS += $(BUSOBJ)/centronics/covox.o BUSOBJS += $(BUSOBJ)/centronics/dsjoy.o BUSOBJS += $(BUSOBJ)/centronics/epson_ex800.o BUSOBJS += $(BUSOBJ)/centronics/epson_lx800.o +BUSOBJS += $(BUSOBJ)/centronics/epson_lx810l.o BUSOBJS += $(BUSOBJ)/centronics/printer.o BUSOBJS += $(BUSOBJ)/centronics/digiblst.o $(BUSOBJ)/centronics/epson_ex800.o: $(EMUOBJ)/layout/ex800.lh $(BUSOBJ)/centronics/epson_lx800.o: $(EMUOBJ)/layout/lx800.lh +$(BUSOBJ)/centronics/epson_lx810l.o: $(EMUOBJ)/layout/lx800.lh endif #------------------------------------------------- diff --git a/src/emu/bus/centronics/ctronics.c b/src/emu/bus/centronics/ctronics.c index b7c87a3b79b..58329364b0a 100644 --- a/src/emu/bus/centronics/ctronics.c +++ b/src/emu/bus/centronics/ctronics.c @@ -119,6 +119,7 @@ device_centronics_peripheral_interface::~device_centronics_peripheral_interface( #include "comxpl80.h" #include "epson_ex800.h" #include "epson_lx800.h" +#include "epson_lx810l.h" #include "printer.h" #include "covox.h" diff --git a/src/emu/bus/centronics/epson_lx800.c b/src/emu/bus/centronics/epson_lx800.c index 96aa229a462..e46f6f18baf 100644 --- a/src/emu/bus/centronics/epson_lx800.c +++ b/src/emu/bus/centronics/epson_lx800.c @@ -15,19 +15,6 @@ input buttons and switches. - CPU disassembly doesn't seem to indicate conditional JR or RET. - - 2014-06-10 Added LX810L, gets caught in a loop almost immediately. - IC list: - * uPD7810HG (cpu) - * E05A30 (gate array) - * 2064C (8k RAM) - * ER59256 (EEP-ROM - serial nvram) - * SLA7020M (step motor driver) - * uPC494C (pulse width modulation control) - May need to be split off to another driver. - - 2014-06-10 Added AP2000, gets caught in the same place as LX810L. - **********************************************************************/ #include "epson_lx800.h" @@ -40,8 +27,6 @@ //************************************************************************** const device_type EPSON_LX800 = &device_creator<epson_lx800_t>; -const device_type EPSON_LX810L = &device_creator<epson_lx810l_t>; -const device_type EPSON_AP2000 = &device_creator<epson_ap2000_t>; //------------------------------------------------- @@ -55,26 +40,6 @@ ROM_END //------------------------------------------------- -// ROM( lx810l ) -//------------------------------------------------- - -ROM_START( lx810l ) - ROM_REGION(0x8000, "maincpu", 0) - ROM_LOAD("lx810l.ic3c", 0x0000, 0x8000, CRC(a66454e1) SHA1(8e6f2f98abcbd8af6e34b9ba746edf0d18aef843) ) -ROM_END - - -//------------------------------------------------- -// ROM( ap2000 ) -//------------------------------------------------- - -ROM_START( ap2000 ) - ROM_REGION(0x8000, "maincpu", 0) - ROM_LOAD("ap2k.ic3c", 0x0000, 0x8000, CRC(ee7294b7) SHA1(219ffa6ff661ce95d5772c9fc1967093718f04e9) ) -ROM_END - - -//------------------------------------------------- // rom_region - device-specific ROM region //------------------------------------------------- @@ -85,26 +50,6 @@ const rom_entry *epson_lx800_t::device_rom_region() const //------------------------------------------------- -// 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( lx800_mem ) //------------------------------------------------- @@ -273,12 +218,6 @@ epson_lx800_t::epson_lx800_t(const machine_config &mconfig, device_type type, co { } -epson_lx810l_t::epson_lx810l_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) - : epson_lx800_t(mconfig, EPSON_LX810L, "Epson LX-810L", tag, owner, clock, "lx810l", __FILE__) { } - -epson_ap2000_t::epson_ap2000_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) - : epson_lx800_t(mconfig, EPSON_AP2000, "Epson ActionPrinter 2000", tag, owner, clock, "ap2000", __FILE__) { } - //------------------------------------------------- // device_start - device-specific startup diff --git a/src/emu/bus/centronics/epson_lx800.h b/src/emu/bus/centronics/epson_lx800.h index 258aeb3230d..1507b34b4d5 100644 --- a/src/emu/bus/centronics/epson_lx800.h +++ b/src/emu/bus/centronics/epson_lx800.h @@ -67,37 +67,9 @@ private: }; -// ======================> epson_lx810l_t - -class epson_lx810l_t : public epson_lx800_t -{ -public: - // construction/destruction - epson_lx810l_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); - - // optional information overrides - virtual const rom_entry *device_rom_region() const; -}; - - -// ======================> epson_ap2000_t - -class epson_ap2000_t : public epson_lx800_t -{ -public: - // construction/destruction - epson_ap2000_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); - - // optional information overrides - virtual const rom_entry *device_rom_region() const; -}; - - // device type definition extern const device_type EPSON_LX800; -extern const device_type EPSON_LX810L; -extern const device_type EPSON_AP2000; diff --git a/src/emu/bus/centronics/epson_lx810l.c b/src/emu/bus/centronics/epson_lx810l.c new file mode 100644 index 00000000000..2882e7cfbc8 --- /dev/null +++ b/src/emu/bus/centronics/epson_lx810l.c @@ -0,0 +1,587 @@ +/* + * Epson LX-810L dot matrix printer emulation + * + * Copyright: 2014 Ramiro Polla + * Felipe Sanches + * License: BSD-3-Clause + * + * 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, but input is not yet implemented. + * + * 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("ic3b", 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("beeper", BEEP, 0) + MCFG_SOUND_ADD("speaker", SPEAKER_SOUND, 0) + MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25) + + /* gate array */ + MCFG_DEVICE_ADD("ic3b", 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)) + + /* 256-bit eeprom */ + MCFG_EEPROM_SERIAL_93C06_ADD("eeprom") +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_eeprom(*this, "eeprom"), + m_speaker(*this, "speaker"), + m_93c06_clk(0), + m_93c06_cs(0), + m_printhead(0), + m_pf_pos_abs(200), + m_cr_pos_abs(200), + m_last_fire(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_eeprom(*this, "eeprom"), + m_speaker(*this, "speaker"), + m_93c06_clk(0), + m_93c06_cs(0), + m_printhead(0), + m_pf_pos_abs(200), + m_cr_pos_abs(200), + m_last_fire(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 +//------------------------------------------------- + +static const stepper_interface lx810l_pf_stepper = +{ + STARPOINT_48STEP_REEL, + 16, + 24, + 0x00, + 0 +}; + +static const stepper_interface lx810l_cr_stepper = +{ + STARPOINT_48STEP_REEL, + 16, + 24, + 0x00, + 2 +}; + +void epson_lx810l_t::device_start() +{ + stepper_config(machine(), 0, &lx810l_pf_stepper); + stepper_config(machine(), 1, &lx810l_cr_stepper); +} + + +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- + +void epson_lx810l_t::device_reset() +{ + m_speaker->level_w(0); +} + + +/*************************************************************************** + 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 ) +{ + stepper_update(0, data); + m_pf_pos_abs = 200 - stepper_get_absolute_position(0); + + LX810LLOG("%s: %s(%02x); abs %d\n", machine().describe_context(), __func__, data, m_pf_pos_abs); +} + +WRITE8_MEMBER( epson_lx810l_t::cr_stepper ) +{ + stepper_update(1, data); + m_cr_pos_abs = 200 - stepper_get_absolute_position(1); + + 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) { + int pos = m_cr_pos_abs; + + /* HACK to get fire positions for motor in movement. The firmware + * issues two half-steps one immediately after the other. A timer + * fires the printhead twice. Supposedly, the first time the + * printhead is fired, it is midway between one step and the other. + * Ideally, the stepper motor interface should model the physics + * of the motors. For the moment, we adjust pos to get the + * intermediate position. + */ + + if (m_cr_pos_abs > m_last_fire + 1) + pos--; + else if (m_cr_pos_abs < m_last_fire - 1) + pos++; + + LX810LLOG("FIRE0 %d %d %04x\n", m_pf_pos_abs, pos, m_printhead); + + m_last_fire = pos; + } +} + +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; +} diff --git a/src/emu/bus/centronics/epson_lx810l.h b/src/emu/bus/centronics/epson_lx810l.h new file mode 100644 index 00000000000..29f80e803e4 --- /dev/null +++ b/src/emu/bus/centronics/epson_lx810l.h @@ -0,0 +1,117 @@ +/* + * Epson LX-810L dot matrix printer emulation + * + * Copyright: 2014 Ramiro Polla + * Felipe Sanches + * License: BSD-3-Clause + */ + +#pragma once + +#ifndef __EPSON_LX810L__ +#define __EPSON_LX810L__ + +#include "emu.h" +#include "ctronics.h" +#include "cpu/upd7810/upd7810.h" +#include "machine/e05a30.h" +#include "machine/eepromser.h" +#include "machine/steppers.h" +#include "sound/beep.h" +#include "sound/speaker.h" + + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + +// ======================> epson_lx810l_t + +class epson_lx810l_t : public device_t, + public device_centronics_peripheral_interface +{ +public: + // construction/destruction + epson_lx810l_t(const machine_config &mconfig, const char *tag, + device_t *owner, UINT32 clock); + 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); + + // optional information overrides + virtual const rom_entry *device_rom_region() const; + virtual machine_config_constructor device_mconfig_additions() const; + virtual ioport_constructor device_input_ports() const; + + DECLARE_READ8_MEMBER(porta_r); + DECLARE_WRITE8_MEMBER(porta_w); + DECLARE_READ8_MEMBER(portb_r); + DECLARE_WRITE8_MEMBER(portb_w); + DECLARE_READ8_MEMBER(portc_r); + DECLARE_WRITE8_MEMBER(portc_w); + + /* Extended Timer Output */ + DECLARE_WRITE_LINE_MEMBER(co0_w); + DECLARE_WRITE_LINE_MEMBER(co1_w); + + /* ADC */ + DECLARE_READ8_MEMBER(an0_r); + DECLARE_READ8_MEMBER(an1_r); + DECLARE_READ8_MEMBER(an2_r); + DECLARE_READ8_MEMBER(an3_r); + DECLARE_READ8_MEMBER(an4_r); + DECLARE_READ8_MEMBER(an5_r); + DECLARE_READ8_MEMBER(an6_r); + DECLARE_READ8_MEMBER(an7_r); + + /* fake memory I/O to get past memory reset check */ + DECLARE_READ8_MEMBER(fakemem_r); + DECLARE_WRITE8_MEMBER(fakemem_w); + + /* GATE ARRAY */ + DECLARE_WRITE16_MEMBER(printhead); + DECLARE_WRITE8_MEMBER(pf_stepper); + DECLARE_WRITE8_MEMBER(cr_stepper); + DECLARE_WRITE_LINE_MEMBER(e05a30_ready); + + /* Panel buttons */ + DECLARE_INPUT_CHANGED_MEMBER(online_sw); + +protected: + // device-level overrides + virtual void device_start(); + virtual void device_reset(); + +private: + required_device<cpu_device> m_maincpu; + required_device<eeprom_serial_93cxx_device> m_eeprom; + required_device<speaker_sound_device> m_speaker; + + int m_93c06_clk; + int m_93c06_cs; + UINT16 m_printhead; + int m_pf_pos_abs; + int m_cr_pos_abs; + int m_last_fire; /* HACK to get fire positions for motor in movement */ + UINT8 m_fakemem; +}; + +// ======================> epson_ap2000_t + +class epson_ap2000_t : public epson_lx810l_t +{ +public: + // construction/destruction + epson_ap2000_t(const machine_config &mconfig, const char *tag, + device_t *owner, UINT32 clock); + + // optional information overrides + virtual const rom_entry *device_rom_region() const; +}; + + +// device type definition +extern const device_type EPSON_LX810L; +extern const device_type EPSON_AP2000; + +#endif diff --git a/src/emu/machine/e05a30.c b/src/emu/machine/e05a30.c new file mode 100644 index 00000000000..d080da38006 --- /dev/null +++ b/src/emu/machine/e05a30.c @@ -0,0 +1,163 @@ +/* + * E05A30 Gate Array (used in the Epson ActionPrinter 2000) + * + * Copyright: 2014 Ramiro Polla + * License: BSD-3-Clause + */ + +#include "emu.h" +#include "e05a30.h" + +//#define E05A30DEBUG +#ifdef E05A30DEBUG +#define LOG(...) fprintf(stderr, __VA_ARGS__) +#else +#define LOG(...) +#endif + + +/***************************************************************************** + DEVICE INTERFACE +*****************************************************************************/ + +const device_type E05A30 = &device_creator<e05a30_device>; + +e05a30_device::e05a30_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : device_t(mconfig, E05A30, "E05A30", tag, owner, clock, "e05a30", __FILE__), + m_write_printhead(*this), + m_write_pf_stepper(*this), + m_write_cr_stepper(*this), + m_write_ready(*this), + m_printhead(0), + m_pf_stepper(0), + m_cr_stepper(0) +{ +} + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void e05a30_device::device_start() +{ + /* resolve callbacks */ + m_write_printhead.resolve_safe(); + m_write_pf_stepper.resolve_safe(); + m_write_cr_stepper.resolve_safe(); + m_write_ready.resolve_safe(); + + /* register for state saving */ + save_item(NAME(m_printhead)); + save_item(NAME(m_pf_stepper)); + save_item(NAME(m_cr_stepper)); +} + +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- + +void e05a30_device::device_reset() +{ + m_printhead = 0x00; + m_pf_stepper = 0x00; + m_cr_stepper = 0x00; + + m_write_ready(1); +} + + +/*************************************************************************** + PRINT HEAD +***************************************************************************/ + +/* The e05a30 controls the printhead through MMIOs 0xC005 and 0xC006. + * MMIO 0xC006 keeps the first 8 pins. + * MMIO 0xC005 keeps the 9th pin in the MSB. + */ + +void e05a30_device::update_printhead(int pos, UINT8 data) +{ + if (pos == 0) { + m_printhead &= 0x00ff; + m_printhead |= (UINT16) !!data << 8; + } else { + m_printhead &= 0xff00; + m_printhead |= data; + } + m_write_printhead(m_printhead); +} + +/*************************************************************************** + STEPPER MOTORS +***************************************************************************/ + +/* The e05a30 controls two stepper motors: + * - The Paper Feed stepper motor is controlled through MMIO 0xC007 + * - The Carriage Return stepper motor is controlled through MMIO 0xC008 + * The Carriage Return stepper motor is used throug the SLA7020M driver. It + * is therefore necessary to translate the input data from the SLA7020M + * format to a format describing the 4 phases of a stepper motor. + * For the PF motor, the output data is fed directly to the stepper motor. + */ + +void e05a30_device::update_pf_stepper(UINT8 data) +{ + m_pf_stepper = data & 0x0f; + m_write_pf_stepper(m_pf_stepper); +} + +static UINT8 cr_sla7020m(UINT8 data) +{ + bool ina = BIT(data, 0); + bool inb = BIT(data, 1); + bool tda = BIT(data, 2); + bool tdb = BIT(data, 3); + bool outa0 = ina && tda; + bool outa1 = !ina && tda; + bool outb0 = inb && tdb; + bool outb1 = !inb && tdb; + return (outb1<<3)|(outb0<<2)|(outa1<<1)|(outa0<<0); +} +void e05a30_device::update_cr_stepper(UINT8 data) +{ + m_cr_stepper = data & 0x0f; + m_write_cr_stepper(cr_sla7020m(m_cr_stepper)); +} + + +/*************************************************************************** + IMPLEMENTATION +***************************************************************************/ + +WRITE8_MEMBER( e05a30_device::write ) +{ + LOG("%s: e05a30_w([0xC0%02x]): %02x\n", space.machine().describe_context(), offset, data); + + switch (offset) { + /* printhead */ + case 0x05: update_printhead(0, data); break; + case 0x06: update_printhead(1, data); break; + /* paper feed stepper motor */ + case 0x07: update_pf_stepper(data); break; + /* carriage return stepper motor */ + case 0x08: update_cr_stepper(data); break; + } +} + +READ8_MEMBER( e05a30_device::read ) +{ + UINT8 result = 0; + + LOG("%s: e05a30_r([0xC0%02x]): ", space.machine().describe_context(), offset); + + switch (offset) { + /* paper feed stepper motor */ + case 0x07: result = m_pf_stepper; break; + /* carriage return stepper motor */ + case 0x08: result = m_cr_stepper; break; + } + + LOG("0x%02x\n", result); + + return result; +} diff --git a/src/emu/machine/e05a30.h b/src/emu/machine/e05a30.h new file mode 100644 index 00000000000..ab32eb21314 --- /dev/null +++ b/src/emu/machine/e05a30.h @@ -0,0 +1,71 @@ +/* + * E05A30 Gate Array (used in the Epson ActionPrinter 2000) + * + * Copyright: 2014 Ramiro Polla + * License: BSD-3-Clause + */ + +#ifndef __E05A30_H__ +#define __E05A30_H__ + +/*************************************************************************** + DEVICE CONFIGURATION MACROS +***************************************************************************/ + +#define MCFG_E05A30_PRINTHEAD_CALLBACK(_write) \ + devcb = &e05a30_device::set_printhead_wr_callback(*device, DEVCB_##_write); + +#define MCFG_E05A30_PF_STEPPER_CALLBACK(_write) \ + devcb = &e05a30_device::set_pf_stepper_wr_callback(*device, DEVCB_##_write); + +#define MCFG_E05A30_CR_STEPPER_CALLBACK(_write) \ + devcb = &e05a30_device::set_cr_stepper_wr_callback(*device, DEVCB_##_write); + +#define MCFG_E05A30_READY_CALLBACK(_write) \ + devcb = &e05a30_device::set_ready_wr_callback(*device, DEVCB_##_write); + +/*************************************************************************** + TYPE DEFINITIONS +***************************************************************************/ + +class e05a30_device : public device_t +{ +public: + e05a30_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + ~e05a30_device() {} + + template<class _Object> static devcb_base &set_printhead_wr_callback(device_t &device, _Object object) { return downcast<e05a30_device &>(device).m_write_printhead.set_callback(object); } + template<class _Object> static devcb_base &set_pf_stepper_wr_callback(device_t &device, _Object object) { return downcast<e05a30_device &>(device).m_write_pf_stepper.set_callback(object); } + template<class _Object> static devcb_base &set_cr_stepper_wr_callback(device_t &device, _Object object) { return downcast<e05a30_device &>(device).m_write_cr_stepper.set_callback(object); } + template<class _Object> static devcb_base &set_ready_wr_callback(device_t &device, _Object object) { return downcast<e05a30_device &>(device).m_write_ready.set_callback(object); } + + DECLARE_WRITE8_MEMBER( write ); + DECLARE_READ8_MEMBER( read ); + +protected: + // device-level overrides + virtual void device_start(); + virtual void device_reset(); + +private: + /* callbacks */ + devcb_write16 m_write_printhead; + devcb_write8 m_write_pf_stepper; + devcb_write8 m_write_cr_stepper; + devcb_write_line m_write_ready; + + void update_printhead(int pos, UINT8 data); + void update_pf_stepper(UINT8 data); + void update_cr_stepper(UINT8 data); + + /* port 0x05 and 0x06 (9-bit) */ + UINT16 m_printhead; + /* port 0x07 (4-bit) */ + UINT8 m_pf_stepper; + /* port 0x08 (4-bit) */ + UINT8 m_cr_stepper; +}; + +extern const device_type E05A30; + +#endif /* __E05A30_H__ */ diff --git a/src/emu/machine/machine.mak b/src/emu/machine/machine.mak index 98ffdd4c8b1..bb71176b4b7 100644 --- a/src/emu/machine/machine.mak +++ b/src/emu/machine/machine.mak @@ -521,6 +521,15 @@ endif #------------------------------------------------- # +#@src/emu/machine/e05a30.h,MACHINES += E05A30 +#------------------------------------------------- + +ifneq ($(filter E05A30,$(MACHINES)),) +MACHINEOBJS += $(MACHINEOBJ)/e05a30.o +endif + +#------------------------------------------------- +# #@src/emu/machine/eeprom.h,MACHINES += EEPROMDEV #@src/emu/machine/eepromser.h,MACHINES += EEPROMDEV #@src/emu/machine/eeprompar.h,MACHINES += EEPROMDEV @@ -1892,6 +1901,15 @@ endif #------------------------------------------------- # +#@src/emu/machine/steppers.h,MACHINES += STEPPERS +#------------------------------------------------- + +ifneq ($(filter STEPPERS,$(MACHINES)),) +MACHINEOBJS += $(MACHINEOBJ)/steppers.o +endif + +#------------------------------------------------- +# #@src/emu/machine/corvushd.h,MACHINES += CORVUSHD #------------------------------------------------- ifneq ($(filter CORVUSHD,$(MACHINES)),) diff --git a/src/mame/machine/steppers.c b/src/emu/machine/steppers.c index 70dfe688d92..70dfe688d92 100644 --- a/src/mame/machine/steppers.c +++ b/src/emu/machine/steppers.c diff --git a/src/mame/machine/steppers.h b/src/emu/machine/steppers.h index db1b30cb1e9..db1b30cb1e9 100644 --- a/src/mame/machine/steppers.h +++ b/src/emu/machine/steppers.h diff --git a/src/mame/mame.mak b/src/mame/mame.mak index b6755456c98..84b500cd810 100644 --- a/src/mame/mame.mak +++ b/src/mame/mame.mak @@ -401,6 +401,7 @@ MACHINES += DS75160A MACHINES += DS75161A MACHINES += E0516 MACHINES += E05A03 +MACHINES += E05A30 MACHINES += EEPROMDEV MACHINES += ER2055 MACHINES += F3853 @@ -564,6 +565,7 @@ MACHINES += FDC37C665GT #MACHINES += SMC92X4 #MACHINES += TI99_HD #MACHINES += STRATA +MACHINES += STEPPERS #MACHINES += CORVUSHD #MACHINES += WOZFDC #MACHINES += DIABLO_HD @@ -954,7 +956,6 @@ $(MAMEOBJ)/barcrest.a: \ $(DRIVERS)/mpu5hw.o $(DRIVERS)/mpu5.o \ $(VIDEO)/awpvid.o \ $(MACHINE)/meters.o \ - $(MACHINE)/steppers.o \ $(MAMEOBJ)/bfm.a: \ $(DRIVERS)/bfcobra.o \ @@ -1289,7 +1290,6 @@ $(MAMEOBJ)/jpm.a: \ $(DRIVERS)/jpmsys7.o \ $(VIDEO)/awpvid.o \ $(MACHINE)/meters.o \ - $(MACHINE)/steppers.o \ $(MAMEOBJ)/kaneko.a: \ $(DRIVERS)/airbustr.o $(VIDEO)/airbustr.o \ diff --git a/src/mess/includes/amstrad.h b/src/mess/includes/amstrad.h index 69bad9589d2..707eb8d157d 100644 --- a/src/mess/includes/amstrad.h +++ b/src/mess/includes/amstrad.h @@ -29,6 +29,7 @@ #include "bus/centronics/comxpl80.h" #include "bus/centronics/epson_ex800.h" #include "bus/centronics/epson_lx800.h" +#include "bus/centronics/epson_lx810l.h" #include "bus/centronics/printer.h" #include "bus/centronics/digiblst.h" #include "bus/generic/slot.h" diff --git a/src/mess/mess.mak b/src/mess/mess.mak index a53c511769c..ba413c73516 100644 --- a/src/mess/mess.mak +++ b/src/mess/mess.mak @@ -387,6 +387,7 @@ MACHINES += DS75160A MACHINES += DS75161A MACHINES += E0516 MACHINES += E05A03 +MACHINES += E05A30 MACHINES += EEPROMDEV MACHINES += ER2055 MACHINES += F3853 @@ -552,6 +553,7 @@ MACHINES += SMC92X4 MACHINES += HDC9234 MACHINES += TI99_HD MACHINES += STRATA +MACHINES += STEPPERS MACHINES += CORVUSHD MACHINES += WOZFDC MACHINES += DIABLO_HD diff --git a/src/targets/mess.lst b/src/targets/mess.lst index 51d297f2636..a1649c51b1f 100644 --- a/src/targets/mess.lst +++ b/src/targets/mess.lst @@ -285,6 +285,7 @@ /mess/drivers/ex800 /mess/drivers/hx20 /mess/drivers/lx800 +/mess/drivers/lx810l /mess/drivers/px4 /mess/drivers/px8 /mess/drivers/qx10 |