summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/bus/centronics
diff options
context:
space:
mode:
Diffstat (limited to 'src/emu/bus/centronics')
-rw-r--r--src/emu/bus/centronics/epson_lx810l.c91
-rw-r--r--src/emu/bus/centronics/epson_lx810l.h27
2 files changed, 92 insertions, 26 deletions
diff --git a/src/emu/bus/centronics/epson_lx810l.c b/src/emu/bus/centronics/epson_lx810l.c
index 2882e7cfbc8..94b24fc3f46 100644
--- a/src/emu/bus/centronics/epson_lx810l.c
+++ b/src/emu/bus/centronics/epson_lx810l.c
@@ -13,7 +13,10 @@
* SLA7020M (step motor driver)
* uPC494C (pulse width modulation control)
*
- * Devices boot and enter main input loop, but input is not yet implemented.
+ * 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;
@@ -99,7 +102,7 @@ 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(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
@@ -140,16 +143,20 @@ static MACHINE_CONFIG_FRAGMENT( epson_lx810l )
/* 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_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")
@@ -273,12 +280,15 @@ epson_lx810l_t::epson_lx810l_t(const machine_config &mconfig, const char *tag, d
m_maincpu(*this, "maincpu"),
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_last_fire(0)
+ m_real_cr_pos(200),
+ m_real_cr_steps(0),
+ m_real_cr_dir(0)
{
}
@@ -288,12 +298,15 @@ epson_lx810l_t::epson_lx810l_t(const machine_config &mconfig, device_type type,
m_maincpu(*this, "maincpu"),
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_last_fire(0)
+ m_real_cr_pos(200),
+ m_real_cr_steps(0),
+ m_real_cr_dir(0)
{
}
@@ -341,6 +354,29 @@ void epson_lx810l_t::device_reset()
}
+//-------------------------------------------------
+// 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
***************************************************************************/
@@ -487,9 +523,23 @@ WRITE8_MEMBER( epson_lx810l_t::pf_stepper )
WRITE8_MEMBER( epson_lx810l_t::cr_stepper )
{
+ int m_cr_pos_abs_prev = m_cr_pos_abs;
+
stepper_update(1, data);
m_cr_pos_abs = 200 - stepper_get_absolute_position(1);
+ 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);
}
@@ -509,25 +559,18 @@ WRITE_LINE_MEMBER( epson_lx810l_t::co0_w )
/* 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.
+ /* 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 =).
*/
-
- 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;
+ LX810LLOG("FIRE0 %d %d %04x\n", m_pf_pos_abs, m_real_cr_pos, m_printhead);
}
}
diff --git a/src/emu/bus/centronics/epson_lx810l.h b/src/emu/bus/centronics/epson_lx810l.h
index 6c40abf50fb..f136af737e1 100644
--- a/src/emu/bus/centronics/epson_lx810l.h
+++ b/src/emu/bus/centronics/epson_lx810l.h
@@ -17,7 +17,6 @@
#include "machine/e05a30.h"
#include "machine/eepromser.h"
#include "machine/steppers.h"
-#include "sound/beep.h"
#include "sound/speaker.h"
@@ -74,6 +73,22 @@ public:
DECLARE_WRITE8_MEMBER(cr_stepper);
DECLARE_WRITE_LINE_MEMBER(e05a30_ready);
+ /* Centronics stuff */
+ virtual DECLARE_WRITE_LINE_MEMBER( input_strobe ) { if (m_e05a30) m_e05a30->centronics_input_strobe(state); }
+ virtual DECLARE_WRITE_LINE_MEMBER( input_data0 ) { if (m_e05a30) m_e05a30->centronics_input_data0(state); }
+ virtual DECLARE_WRITE_LINE_MEMBER( input_data1 ) { if (m_e05a30) m_e05a30->centronics_input_data1(state); }
+ virtual DECLARE_WRITE_LINE_MEMBER( input_data2 ) { if (m_e05a30) m_e05a30->centronics_input_data2(state); }
+ virtual DECLARE_WRITE_LINE_MEMBER( input_data3 ) { if (m_e05a30) m_e05a30->centronics_input_data3(state); }
+ virtual DECLARE_WRITE_LINE_MEMBER( input_data4 ) { if (m_e05a30) m_e05a30->centronics_input_data4(state); }
+ virtual DECLARE_WRITE_LINE_MEMBER( input_data5 ) { if (m_e05a30) m_e05a30->centronics_input_data5(state); }
+ virtual DECLARE_WRITE_LINE_MEMBER( input_data6 ) { if (m_e05a30) m_e05a30->centronics_input_data6(state); }
+ virtual DECLARE_WRITE_LINE_MEMBER( input_data7 ) { if (m_e05a30) m_e05a30->centronics_input_data7(state); }
+ DECLARE_WRITE_LINE_MEMBER(e05a30_centronics_ack) { output_ack(state); }
+ DECLARE_WRITE_LINE_MEMBER(e05a30_centronics_busy) { output_busy(state); }
+ DECLARE_WRITE_LINE_MEMBER(e05a30_centronics_perror) { output_perror(state); }
+ DECLARE_WRITE_LINE_MEMBER(e05a30_centronics_fault) { output_fault(state); }
+ DECLARE_WRITE_LINE_MEMBER(e05a30_centronics_select) { output_select(state); }
+
/* Panel buttons */
DECLARE_INPUT_CHANGED_MEMBER(online_sw);
@@ -81,19 +96,27 @@ protected:
// device-level overrides
virtual void device_start();
virtual void device_reset();
+ virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
private:
required_device<cpu_device> m_maincpu;
required_device<eeprom_serial_93cxx_device> m_eeprom;
required_device<speaker_sound_device> m_speaker;
+ required_device<e05a30_device> m_e05a30;
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 */
+ int m_real_cr_pos;
+ int m_real_cr_steps;
+ int m_real_cr_dir; /* 1 is going right, -1 is going left */
UINT8 m_fakemem;
+
+ enum {
+ TIMER_CR,
+ };
};
// ======================> epson_ap2000_t