From c1f4b4600a0db14cfdd775b86fa100af32b65698 Mon Sep 17 00:00:00 2001 From: AJR Date: Fri, 9 Jun 2023 21:00:50 -0400 Subject: sed1200: Modernize emulation - Reduce bus to 4 bits (but note that an 8-bit variant exists), and add CS write handler to ensure multiple writes go to the correct nibbles. This results in considerable uglification of the mt32 driver code, but is more hardware-accurate. - Speculatively eliminate cursor wraparound at first and last positions. This may or may not be accurate, but seems to produce neater results. - Save state of internal variables. --- src/devices/video/sed1200.cpp | 112 +++++++++++++++++++++++++++++++--------- src/devices/video/sed1200.h | 11 +++- src/mame/roland/roland_mt32.cpp | 10 +++- 3 files changed, 104 insertions(+), 29 deletions(-) diff --git a/src/devices/video/sed1200.cpp b/src/devices/video/sed1200.cpp index 371832f579a..88503354873 100644 --- a/src/devices/video/sed1200.cpp +++ b/src/devices/video/sed1200.cpp @@ -4,7 +4,9 @@ SED1200 - A LCD controller. + A LCD controller similar to HD44780/SED1278 that drives a 20-character + display. Data input is 4 bits at a time. (SED1210 has a 40-character + display and 8-bit data input.) The D/F variants have a packaging difference (QFP80 vs. bare chip). @@ -16,10 +18,10 @@ #include "emu.h" #include "sed1200.h" -DEFINE_DEVICE_TYPE(SED1200D0A, sed1200d0a_device, "sed1200da", "Epson SED1200D-0A") -DEFINE_DEVICE_TYPE(SED1200F0A, sed1200f0a_device, "sed1200fa", "Epson SED1200F-0A") -DEFINE_DEVICE_TYPE(SED1200D0B, sed1200d0b_device, "sed1200db", "Epson SED1200D-0B") -DEFINE_DEVICE_TYPE(SED1200F0B, sed1200f0b_device, "sed1200fb", "Epson SED1200F-0B") +DEFINE_DEVICE_TYPE(SED1200D0A, sed1200d0a_device, "sed1200da", "Epson SED1200D-0A LCD Controller") +DEFINE_DEVICE_TYPE(SED1200F0A, sed1200f0a_device, "sed1200fa", "Epson SED1200F-0A LCD Controller") +DEFINE_DEVICE_TYPE(SED1200D0B, sed1200d0b_device, "sed1200db", "Epson SED1200D-0B LCD Controller") +DEFINE_DEVICE_TYPE(SED1200F0B, sed1200f0b_device, "sed1200fb", "Epson SED1200F-0B LCD Controller") ROM_START( sed1200x0a ) ROM_REGION( 0x800, "cgrom", 0 ) @@ -31,28 +33,40 @@ ROM_START( sed1200x0b ) ROM_LOAD( "sed1200-b.bin", 0x000, 0x800, CRC(d0741f51) SHA1(c8c856f1357286a2c8c806af81724a828345357e)) ROM_END -sed1200_device::sed1200_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) : - device_t(mconfig, type, tag, owner, clock), cursor_direction(false), cursor_blinking(false), cursor_full(false), cursor_on(false), display_on(false), cursor_address(0), cgram_address(0), cgrom(nullptr) +sed1200_device::sed1200_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) + : device_t(mconfig, type, tag, owner, clock) + , cursor_direction(false) + , cursor_blinking(false) + , cursor_full(false) + , cursor_on(false) + , display_on(false) + , two_lines(false) + , cursor_address(0) + , cgram_address(0) + , cgrom(nullptr) + , chip_select(false) + , first_input(false) + , first_data(0) { } -sed1200d0a_device::sed1200d0a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : - sed1200_device(mconfig, SED1200D0A, tag, owner, clock) +sed1200d0a_device::sed1200d0a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : sed1200_device(mconfig, SED1200D0A, tag, owner, clock) { } -sed1200f0a_device::sed1200f0a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : - sed1200_device(mconfig, SED1200F0A, tag, owner, clock) +sed1200f0a_device::sed1200f0a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : sed1200_device(mconfig, SED1200F0A, tag, owner, clock) { } -sed1200d0b_device::sed1200d0b_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : - sed1200_device(mconfig, SED1200D0B, tag, owner, clock) +sed1200d0b_device::sed1200d0b_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : sed1200_device(mconfig, SED1200D0B, tag, owner, clock) { } -sed1200f0b_device::sed1200f0b_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : - sed1200_device(mconfig, SED1200F0B, tag, owner, clock) +sed1200f0b_device::sed1200f0b_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : sed1200_device(mconfig, SED1200F0B, tag, owner, clock) { } @@ -85,9 +99,33 @@ void sed1200_device::device_start() else cgrom = nullptr; + chip_select = false; + + save_item(NAME(cgram)); + save_item(NAME(ddram)); + save_item(NAME(cursor_direction)); + save_item(NAME(cursor_blinking)); + save_item(NAME(cursor_full)); + save_item(NAME(cursor_on)); + save_item(NAME(display_on)); + save_item(NAME(two_lines)); + save_item(NAME(cursor_address)); + save_item(NAME(cgram_address)); + save_item(NAME(chip_select)); + save_item(NAME(first_input)); + save_item(NAME(first_data)); + soft_reset(); } +void sed1200_device::cs_w(int state) +{ + if (chip_select != !state) { + chip_select = !state; + first_input = true; + } +} + void sed1200_device::soft_reset() { cursor_direction = false; @@ -95,11 +133,23 @@ void sed1200_device::soft_reset() cursor_full = false; cursor_on = false; display_on = false; + two_lines = false; cursor_address = 0x00; cgram_address = 0x00; } void sed1200_device::control_w(uint8_t data) +{ + if(chip_select) { + if(first_input) + first_data = data & 0x0f; + else + control_write(first_data << 4 | (data & 0x0f)); + first_input = !first_input; + } +} + +void sed1200_device::control_write(uint8_t data) { switch(data) { case 0x04: case 0x05: @@ -124,7 +174,8 @@ void sed1200_device::control_w(uint8_t data) soft_reset(); break; case 0x12: case 0x13: - break; // Number of lines selection + two_lines = data & 0x01; + break; default: if((data & 0xf0) == 0x20) cgram_address = (data & 3)*8; @@ -133,19 +184,34 @@ void sed1200_device::control_w(uint8_t data) if(cgram_address == 4*8) cgram_address = 0; } else if(data & 0x80) { - cursor_address = data & 0x40 ? 10 : 0; - cursor_address += (data & 0x3f) >= 10 ? 9 : data & 0x3f; + if (two_lines) { + cursor_address = data & 0x40 ? 10 : 0; + cursor_address += (data & 0x3f) >= 10 ? 9 : data & 0x3f; + } else + cursor_address = (data & 0x3f) >= 20 ? 19 : data & 0x3f; } break; } } -uint8_t sed1200_device::control_r() +uint8_t sed1200_device::busy_r() { + // TODO: bit 3 = busy flag return 0x00; } void sed1200_device::data_w(uint8_t data) +{ + if(chip_select) { + if(first_input) + first_data = data & 0x0f; + else + data_write(first_data << 4 | (data & 0x0f)); + first_input = !first_input; + } +} + +void sed1200_device::data_write(uint8_t data) { ddram[cursor_address] = data; cursor_step(); @@ -154,14 +220,10 @@ void sed1200_device::data_w(uint8_t data) void sed1200_device::cursor_step() { if(cursor_direction) { - if(cursor_address == 0 || cursor_address == 10) - cursor_address += 9; - else + if(cursor_address != 0 && (!two_lines || cursor_address != 10)) cursor_address --; } else { - if(cursor_address == 9 || cursor_address == 19) - cursor_address -= 9; - else + if((!two_lines || cursor_address != 9) && cursor_address != 19) cursor_address ++; } } diff --git a/src/devices/video/sed1200.h b/src/devices/video/sed1200.h index d6590af49ab..480ff9b454e 100644 --- a/src/devices/video/sed1200.h +++ b/src/devices/video/sed1200.h @@ -20,8 +20,9 @@ class sed1200_device : public device_t { public: + void cs_w(int state); void control_w(uint8_t data); - uint8_t control_r(); + uint8_t busy_r(); void data_w(uint8_t data); const uint8_t *render(); @@ -35,10 +36,16 @@ private: uint8_t cgram[4*8]; uint8_t ddram[10*2]; uint8_t render_buf[20*8]; - bool cursor_direction, cursor_blinking, cursor_full, cursor_on, display_on; + bool cursor_direction, cursor_blinking, cursor_full, cursor_on, display_on, two_lines; uint8_t cursor_address, cgram_address; const uint8_t *cgrom; + bool chip_select, first_input; + uint8_t first_data; + + void control_write(uint8_t data); + void data_write(uint8_t data); + void soft_reset(); void cursor_step(); }; diff --git a/src/mame/roland/roland_mt32.cpp b/src/mame/roland/roland_mt32.cpp index cba45237154..4a75aac74ee 100644 --- a/src/mame/roland/roland_mt32.cpp +++ b/src/mame/roland/roland_mt32.cpp @@ -275,15 +275,21 @@ void mt32_state::machine_reset() void mt32_state::lcd_ctrl_w(uint8_t data) { + lcd->cs_w(0); + lcd->control_w(data >> 4); lcd->control_w(data); - for(int i=0; i != lcd_data_buffer_pos; i++) + for(int i=0; i != lcd_data_buffer_pos; i++) { + lcd->data_w(lcd_data_buffer[i] >> 4); lcd->data_w(lcd_data_buffer[i]); + } + lcd->cs_w(1); lcd_data_buffer_pos = 0; } uint8_t mt32_state::lcd_ctrl_r() { - return lcd->control_r(); + // Note that this does not read from the actual LCD unit (whose /RD line is pulled high) + return 0; } void mt32_state::lcd_data_w(uint8_t data) -- cgit v1.2.3