From 5830838f26b95ac0da871ad6f2fc45fb0b0c5adb Mon Sep 17 00:00:00 2001 From: hap Date: Mon, 23 Jan 2017 23:44:39 +0100 Subject: [PATCH] hlcd0515: couple of accuracy improvements (nw) --- src/devices/video/hlcd0515.cpp | 121 ++++++++++++++++++++------------- src/devices/video/hlcd0515.h | 21 ++++-- src/mame/drivers/hh_tms1k.cpp | 2 +- 3 files changed, 91 insertions(+), 53 deletions(-) diff --git a/src/devices/video/hlcd0515.cpp b/src/devices/video/hlcd0515.cpp index 052c3ba4933..498ecf44316 100644 --- a/src/devices/video/hlcd0515.cpp +++ b/src/devices/video/hlcd0515.cpp @@ -3,10 +3,12 @@ /* Hughes HLCD 0515/0569 LCD Driver + + 0515: 25 columns(also size of buffer/ram) + 0569: 24 columns, no DATA OUT pin, display blank has no effect TODO: - - What's the difference between 0515 and 0569? For now assume 0569 is a cost-reduced chip, - lacking the data out pin. + - read mode is untested - MAME bitmap update callback when needed */ @@ -21,20 +23,19 @@ const device_type HLCD0569 = &device_creator; // constructor //------------------------------------------------- -hlcd0515_device::hlcd0515_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) - : device_t(mconfig, HLCD0515, "HLCD 0515 LCD Driver", tag, owner, clock, "hlcd0515", __FILE__), - m_write_cols(*this), m_write_data(*this) +hlcd0515_device::hlcd0515_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, u32 clock, u8 colmax, const char *shortname, const char *source) + : device_t(mconfig, type, name, tag, owner, clock, shortname, source), + m_colmax(colmax), m_write_cols(*this), m_write_data(*this) { } -hlcd0515_device::hlcd0515_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, u32 clock, const char *shortname, const char *source) - : device_t(mconfig, type, name, tag, owner, clock, shortname, source), - m_write_cols(*this), m_write_data(*this) +hlcd0515_device::hlcd0515_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : hlcd0515_device(mconfig, HLCD0515, "HLCD 0515 LCD Driver", tag, owner, clock, 25, "hlcd0515", __FILE__) { } hlcd0569_device::hlcd0569_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) - : hlcd0515_device(mconfig, HLCD0569, "HLCD 0569 LCD Driver", tag, owner, clock, "hlcd0569", __FILE__) + : hlcd0515_device(mconfig, HLCD0569, "HLCD 0569 LCD Driver", tag, owner, clock, 24, "hlcd0569", __FILE__) { } @@ -64,6 +65,7 @@ void hlcd0515_device::device_start() m_rowmax = 0; m_rowout = 0; m_rowsel = 0; + m_buffer = 0; memset(m_ram, 0, sizeof(m_ram)); // register for savestates @@ -76,6 +78,7 @@ void hlcd0515_device::device_start() save_item(NAME(m_rowmax)); save_item(NAME(m_rowout)); save_item(NAME(m_rowsel)); + save_item(NAME(m_buffer)); save_item(NAME(m_ram)); } @@ -101,7 +104,7 @@ void hlcd0515_device::device_timer(emu_timer &timer, device_timer_id id, int par m_rowout = 0; // write to COL/ROW pins - m_write_cols(m_rowout, m_blank ? m_ram[m_rowout] : 0, 0xffffffff); + m_write_cols(m_rowout, m_blank ? 0 : m_ram[m_rowout], 0xffffffff); m_rowout++; } @@ -111,68 +114,92 @@ void hlcd0515_device::device_timer(emu_timer &timer, device_timer_id id, int par // handlers //------------------------------------------------- -WRITE_LINE_MEMBER(hlcd0515_device::write_cs) +void hlcd0515_device::set_control() { - state = (state) ? 1 : 0; + // clock 0,1,2: row select + m_rowsel = m_control >> 2 & 7; - // start serial sequence on falling edge - if (!state && m_cs) + // clock 3(,4): initialize + if (m_control & 2) { - m_count = 0; - m_control = 0; + m_rowmax = m_rowsel; + m_blank = bool(~m_control & 1); } - m_cs = state; + // clock 4: read/write mode + if (m_control & 1) + m_buffer = m_ram[m_rowsel]; } +void hlcd0569_device::set_control() +{ + hlcd0515_device::set_control(); + m_blank = false; // 0569 doesn't support display blanking +} + + +void hlcd0515_device::clock_data(int col) +{ + if (m_control & 1) + { + if (col < m_colmax) + m_buffer <<= 1; + + m_write_data(m_buffer >> m_colmax & 1); + } + else + { + if (col < m_colmax) + m_buffer >>= 1; + + // always write last column + u32 mask = 1 << (m_colmax - 1); + m_buffer = (m_buffer & ~mask) | (m_data ? mask : 0); + } +} + + WRITE_LINE_MEMBER(hlcd0515_device::write_clock) { state = (state) ? 1 : 0; // clock/shift data on falling edge - if (!m_cs && m_count < 30 && !state && m_clock) + if (!m_cs && !state && m_clock) { if (m_count < 5) { // 5-bit mode/control m_control = m_control << 1 | m_data; - if (m_count == 4) - { - // clock 0,1,2: row select - // clock 3: initialize - // clock 4: read/write - m_rowsel = m_control >> 2 & 7; - if (m_control & 2) - { - m_rowmax = m_rowsel; - m_blank = bool(m_control & 1); - } - } + set_control(); } else - { - if (m_control & 1) - { - // read data, output - m_write_data(m_ram[m_rowsel] >> (m_count - 5) & 1); - } - else - { - // write data - u32 mask = 1 << (m_count - 5); - m_ram[m_rowsel] = (m_ram[m_rowsel] & ~mask) | (m_data ? mask : 0); - } - } - - m_count++; + clock_data(m_count - 5); + + if (m_count < (m_colmax + 5)) + m_count++; } m_clock = state; } -WRITE_LINE_MEMBER(hlcd0515_device::write_data) + +WRITE_LINE_MEMBER(hlcd0515_device::write_cs) { - m_data = (state) ? 1 : 0; + state = (state) ? 1 : 0; + + // finish serial sequence on rising edge + if (state && !m_cs) + { + // transfer to ram + if (~m_control & 1) + m_ram[m_rowsel] = m_buffer; + + m_count = 0; + m_control = 0; + m_buffer = 0; + } + + m_cs = state; } diff --git a/src/devices/video/hlcd0515.h b/src/devices/video/hlcd0515.h index 622a68e7126..a09af404b55 100644 --- a/src/devices/video/hlcd0515.h +++ b/src/devices/video/hlcd0515.h @@ -16,7 +16,7 @@ #define MCFG_HLCD0515_WRITE_COLS_CB(_devcb) \ hlcd0515_device::set_write_cols_callback(*device, DEVCB_##_devcb); -// DATA OUT pin +// DATA OUT pin, don't use on HLCD0569 #define MCFG_HLCD0515_WRITE_DATA_CB(_devcb) \ hlcd0515_device::set_write_data_callback(*device, DEVCB_##_devcb); @@ -46,6 +46,8 @@ COL11 19 | | 22 COL13 GND 20 |___________| 21 COL12 + HLCD 0569 doesn't have DATA OUT, instead it has what seems like OSC OUT on pin 34. + OSC is tied to a capacitor, the result frequency is 50000 * cap(in uF), eg. 0.01uF cap = 500Hz. Internally, this is divided by 2, and by number of rows to get display refresh frequency. */ @@ -54,15 +56,15 @@ class hlcd0515_device : public device_t { public: hlcd0515_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); - hlcd0515_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, u32 clock, const char *shortname, const char *source); + hlcd0515_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, u32 clock, u8 colmax, const char *shortname, const char *source); // static configuration helpers template static devcb_base &set_write_cols_callback(device_t &device, _Object object) { return downcast(device).m_write_cols.set_callback(object); } template static devcb_base &set_write_data_callback(device_t &device, _Object object) { return downcast(device).m_write_data.set_callback(object); } - DECLARE_WRITE_LINE_MEMBER(write_cs); DECLARE_WRITE_LINE_MEMBER(write_clock); - DECLARE_WRITE_LINE_MEMBER(write_data); + DECLARE_WRITE_LINE_MEMBER(write_cs); + DECLARE_WRITE_LINE_MEMBER(write_data) { m_data = (state) ? 1 : 0; } protected: // device-level overrides @@ -70,6 +72,11 @@ protected: virtual void device_reset() override; virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override; + virtual void set_control(); + void clock_data(int col); + + u8 m_colmax; // number of column pins + int m_cs; // input pin state int m_clock; // " int m_data; // " @@ -79,7 +86,8 @@ protected: u8 m_rowmax; // number of rows output by lcd (max 8) u8 m_rowout; // current row for lcd output u8 m_rowsel; // current row for data in/out - u32 m_ram[8]; // 8x25bit ram + u32 m_buffer; // data in/out shift register + u32 m_ram[8]; // internal lcd ram, 8 rows emu_timer *m_lcd_timer; @@ -93,6 +101,9 @@ class hlcd0569_device : public hlcd0515_device { public: hlcd0569_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); + +protected: + virtual void set_control() override; }; diff --git a/src/mame/drivers/hh_tms1k.cpp b/src/mame/drivers/hh_tms1k.cpp index bd4d6191b61..0e01bc94f2d 100644 --- a/src/mame/drivers/hh_tms1k.cpp +++ b/src/mame/drivers/hh_tms1k.cpp @@ -19,6 +19,7 @@ @CP0904A TMS0970 1977, Milton Bradley Comp IV @MP0905B TMS0970 1977, Parker Brothers Codename Sector *MP0057 TMS1000 1978, APH Student Speech+ (same ROM contents as TSI Speech+?) + *MP0154 TMS1000 1979, Fonas 2 Player Baseball @MP0158 TMS1000 1979, Entex Soccer (6003) @MP0163 TMS1000 1979, A-One LSI Match Number/LJN Electronic Concentration @MP0168 TMS1000 1979, Conic Multisport/Tandy Sports Arena (model 60-2158) @@ -4823,7 +4824,6 @@ WRITE16_MEMBER(comp4_state::write_o) // O0: leds common // other bits: N/C m_o = data; - display_matrix(11, 1, m_r, m_o); } READ8_MEMBER(comp4_state::read_k)