Merge pull request #335 from ramiropolla/lx810l

lx810l: add screen simulating paper output
This commit is contained in:
Olivier Galibert 2015-09-19 22:51:31 +02:00
commit 12a6bc6aa6
3 changed files with 83 additions and 40 deletions

View File

@ -2,7 +2,7 @@
// copyright-holders:Ramiro Polla, Felipe Sanches
/*
* Epson LX-810L dot matrix printer emulation
*
* IC list:
* uPD7810HG (cpu)
* E05A30 (gate array)
@ -12,9 +12,7 @@
* 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.
* centronics bus and printed as expected in a separate screen.
*
* It is possible to run the printers' self test with this procedure:
* - Turn on device;
@ -22,12 +20,9 @@
* - 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()).
* The printer's carriage will seek home and it will start printing
* some test data. The Online LED will blink at each line.
*/
#include "epson_lx810l.h"
@ -139,9 +134,17 @@ static MACHINE_CONFIG_FRAGMENT( epson_lx810l )
MCFG_DEFAULT_LAYOUT(layout_lx800)
/* video hardware (simulates paper) */
MCFG_SCREEN_ADD("screen", RASTER)
MCFG_SCREEN_REFRESH_RATE(60)
MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(0))
MCFG_SCREEN_SIZE(PAPER_WIDTH, PAPER_HEIGHT)
MCFG_SCREEN_VISIBLE_AREA(0, PAPER_WIDTH-1, 0, PAPER_HEIGHT-1)
MCFG_SCREEN_UPDATE_DRIVER(epson_lx810l_t, screen_update_lx810l)
/* audio hardware */
MCFG_SPEAKER_STANDARD_MONO("mono")
MCFG_SOUND_ADD("speaker", SPEAKER_SOUND, 0)
MCFG_DAC_ADD("dac")
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25)
/* gate array */
@ -160,19 +163,12 @@ static MACHINE_CONFIG_FRAGMENT( epson_lx810l )
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_INIT_PHASE(4)
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
@ -296,14 +292,15 @@ epson_lx810l_t::epson_lx810l_t(const machine_config &mconfig, const char *tag, d
m_pf_stepper(*this, "pf_stepper"),
m_cr_stepper(*this, "cr_stepper"),
m_eeprom(*this, "eeprom"),
m_speaker(*this, "speaker"),
m_dac(*this, "dac"),
m_e05a30(*this, "e05a30"),
m_screen(*this, "screen"),
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_pf_pos_abs(1),
m_cr_pos_abs(1),
m_real_cr_pos(1),
m_real_cr_steps(0),
m_real_cr_dir(0)
{
@ -316,14 +313,15 @@ epson_lx810l_t::epson_lx810l_t(const machine_config &mconfig, device_type type,
m_pf_stepper(*this, "pf_stepper"),
m_cr_stepper(*this, "cr_stepper"),
m_eeprom(*this, "eeprom"),
m_speaker(*this, "speaker"),
m_dac(*this, "dac"),
m_e05a30(*this, "e05a30"),
m_screen(*this, "screen"),
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_pf_pos_abs(1),
m_cr_pos_abs(1),
m_real_cr_pos(1),
m_real_cr_steps(0),
m_real_cr_dir(0)
{
@ -343,6 +341,8 @@ epson_ap2000_t::epson_ap2000_t(const machine_config &mconfig, const char *tag, d
void epson_lx810l_t::device_start()
{
machine().first_screen()->register_screen_bitmap(m_bitmap);
m_bitmap.fill(0xffffff); /* Start with a clean white piece of paper */
}
@ -352,7 +352,7 @@ void epson_lx810l_t::device_start()
void epson_lx810l_t::device_reset()
{
m_speaker->level_w(0);
m_dac->write_unsigned8(0);
}
@ -517,8 +517,14 @@ WRITE16_MEMBER( epson_lx810l_t::printhead )
WRITE8_MEMBER( epson_lx810l_t::pf_stepper )
{
m_pf_stepper->update(data);
m_pf_pos_abs = 200 - m_pf_stepper->get_absolute_position();
int changed = m_pf_stepper->update(data);
m_pf_pos_abs = -m_pf_stepper->get_absolute_position();
/* clear last line of paper */
if (changed > 0) {
void *line = m_bitmap.raw_pixptr(bitmap_line(9), 0);
memset(line, 0xff, m_bitmap.width() * 4);
}
LX810LLOG("%s: %s(%02x); abs %d\n", machine().describe_context(), __func__, data, m_pf_pos_abs);
}
@ -528,7 +534,7 @@ 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();
m_cr_pos_abs = -m_cr_stepper->get_absolute_position();
if (m_cr_pos_abs > m_cr_pos_abs_prev) {
/* going right */
@ -551,14 +557,28 @@ WRITE_LINE_MEMBER( epson_lx810l_t::e05a30_ready )
}
/***************************************************************************
Video hardware (simulates paper)
***************************************************************************/
UINT32 epson_lx810l_t::screen_update_lx810l(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
int scrolly = -bitmap_line(9);
copyscrollbitmap(bitmap, m_bitmap, 0, NULL, 1, &scrolly, cliprect);
/* draw "printhead" */
bitmap.plot_box(m_real_cr_pos + CR_OFFSET - 10, PAPER_HEIGHT - 36, 20, 36, 0x888888);
return 0;
}
/***************************************************************************
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
@ -572,13 +592,19 @@ WRITE_LINE_MEMBER( epson_lx810l_t::co0_w )
* 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);
if (m_real_cr_pos < m_bitmap.width()) {
for (int i = 0; i < 9; i++) {
unsigned int y = bitmap_line(i);
if ((m_printhead & (1<<(8-i))) != 0)
m_bitmap.pix32(y, m_real_cr_pos + CR_OFFSET) = 0x000000;
}
}
}
}
WRITE_LINE_MEMBER( epson_lx810l_t::co1_w )
{
m_speaker->level_w(state);
m_dac->write_unsigned8(0 - !state);
}

View File

@ -16,9 +16,19 @@
#include "machine/e05a30.h"
#include "machine/eepromser.h"
#include "machine/steppers.h"
#include "sound/speaker.h"
#include "sound/dac.h"
/* The printer starts printing at x offset 44 and stops printing at x
* offset 1009, giving a total of 965 printable pixels. Supposedly, the
* border at the far right would be at x offset 1053. I've chosen the
* width for the paper as 1024, since it's a nicer number than 1053, so
* an offset must be used to centralize the pixels.
*/
#define CR_OFFSET (-14)
#define PAPER_WIDTH 1024
#define PAPER_HEIGHT 576
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
@ -91,6 +101,11 @@ public:
/* Panel buttons */
DECLARE_INPUT_CHANGED_MEMBER(online_sw);
/* Video hardware (simulates paper) */
UINT32 screen_update_lx810l(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
#define uabs(x) ((x) > 0 ? (x) : -(x))
unsigned int bitmap_line(int i) { return ((uabs(m_pf_pos_abs) / 6) + i) % m_bitmap.height(); }
protected:
// device-level overrides
virtual void device_start();
@ -102,8 +117,9 @@ private:
required_device<stepper_device> m_pf_stepper;
required_device<stepper_device> m_cr_stepper;
required_device<eeprom_serial_93cxx_device> m_eeprom;
required_device<speaker_sound_device> m_speaker;
required_device<dac_device> m_dac;
required_device<e05a30_device> m_e05a30;
required_device<screen_device> m_screen;
int m_93c06_clk;
int m_93c06_cs;
@ -114,6 +130,7 @@ private:
int m_real_cr_steps;
int m_real_cr_dir; /* 1 is going right, -1 is going left */
UINT8 m_fakemem;
bitmap_rgb32 m_bitmap;
enum {
TIMER_CR

View File

@ -97,11 +97,11 @@ void e05a30_device::device_reset()
void e05a30_device::update_printhead(int pos, UINT8 data)
{
if (pos == 0) {
m_printhead &= 0x00ff;
m_printhead |= (UINT16) !!data << 8;
m_printhead &= 0x01fe;
m_printhead |= (data >> 7);
} else {
m_printhead &= 0xff00;
m_printhead |= data;
m_printhead &= 0x0001;
m_printhead |= (UINT16) (data << 1);
}
m_write_printhead(m_printhead);
}