From e19fc2e32606e54ca4dffe3cb23013d395300c3e Mon Sep 17 00:00:00 2001 From: AJR Date: Sat, 2 Nov 2024 08:46:21 -0400 Subject: [PATCH] Add Novatek NT7502 LCD Driver as SED1560 variant --- src/devices/video/sed1520.cpp | 68 ++++++++++++++++++++++++++++- src/devices/video/sed1520.h | 22 ++++++++++ src/mame/benesse/challenge_gear.cpp | 33 +++++++++----- 3 files changed, 111 insertions(+), 12 deletions(-) diff --git a/src/devices/video/sed1520.cpp b/src/devices/video/sed1520.cpp index de559af4f9a..3b0c8bc2040 100644 --- a/src/devices/video/sed1520.cpp +++ b/src/devices/video/sed1520.cpp @@ -5,6 +5,7 @@ SED1520 LCD controller SED1560 LCD controller EPL43102 LCD controller + NT7502 LCD controller TODO: - busy flag @@ -24,6 +25,7 @@ DEFINE_DEVICE_TYPE(SED1520, sed1520_device, "sed1520", "Epson SED1520 LCD Driver") DEFINE_DEVICE_TYPE(SED1560, sed1560_device, "sed1560", "Epson SED1560 LCD Driver") DEFINE_DEVICE_TYPE(EPL43102, epl43102_device, "epl43102", "Elan EPL43102 LCD Driver") +DEFINE_DEVICE_TYPE(NT7502, nt7502_device, "nt7502", "Novatek NT7502 LCD Driver") //************************************************************************** @@ -69,7 +71,12 @@ sed1560_device::sed1560_device(const machine_config &mconfig, const char *tag, d } epl43102_device::epl43102_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : sed1560_device(mconfig, EPL43102, tag, owner, clock, 455, 102) // 102 × 43-bit display RAM (TODO: page map is not straightforward) + : sed1560_device(mconfig, EPL43102, tag, owner, clock, 714, 102) // 102 × 43-bit display RAM (TODO: page map is not straightforward) +{ +} + +nt7502_device::nt7502_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : sed1560_device(mconfig, NT7502, tag, owner, clock, 1188, 166) // 132 × 65-bit display RAM { } @@ -174,6 +181,14 @@ void epl43102_device::device_start() save_item(NAME(m_last_command)); } +void nt7502_device::device_start() +{ + sed1560_device::device_start(); + + // state saving + save_item(NAME(m_last_command)); +} + //------------------------------------------------- // device_reset - device-specific reset //------------------------------------------------- @@ -198,6 +213,13 @@ void epl43102_device::device_reset() m_last_command = 0; } +void nt7502_device::device_reset() +{ + sed1560_device::device_reset(); + + m_last_command = 0; +} + //************************************************************************** // device interface //************************************************************************** @@ -404,6 +426,50 @@ void epl43102_device::control_write(uint8_t data) } +void nt7502_device::control_write(uint8_t data) +{ + switch (m_last_command) + { + case 0x81: + m_contrast = data & 0x3f; + m_last_command = 0; + break; + + case 0xad: + if ((data & 0x03) == 0) + logerror("%s: Status indicator off\n", machine().describe_context()); + else + logerror("%s: Status indicator on (%s)\n", machine().describe_context(), (data & 0x03) == 0x01 ? "0.5-second blinking" : (data & 0x03) == 0x02 ? "1-second blinking" : "continuously"); + m_last_command = 0; + break; + + default: + if (data == 0x81 || data == 0xad) + { + // 2-byte instructions + m_last_command = data; + } + else if ((data & 0xfe) == 0xa2) + logerror("%s: LCD voltage bias = %s\n", machine().describe_context(), BIT(data, 0) ? "1/5, 1/6 or 1/7" : "1/7, 1/8 or 1/9"); + else if ((data & 0xf0) == 0xc0) + logerror("%s: COM output direction = %s\n", machine().describe_context(), BIT(data, 3) ? "reverse" : "normal"); + else if ((data & 0xf8) == 0x28) + logerror("%s: Voltage booster %s, regulator %s, follower %s\n", machine().describe_context(), BIT(data, 2) ? "on" : "off", BIT(data, 1) ? "on" : "off", BIT(data, 0) ? "on" : "off"); + else if ((data & 0xf8) == 0x20) + logerror("%s: V0 voltage regulator internal resistor select = %d\n", machine().describe_context(), data & 0x07); + else if (data == 0xac) + logerror("%s: Static indicator off\n", machine().describe_context()); + else if (data == 0xe3) + /* NOP command */; + else if ((data & 0xf0) == 0xf0) + logerror("%s: Test mode %s (%02X)\n", machine().describe_context(), data == 0xf0 ? "reset" : "on", data); + else + sed1560_device::control_write(data); + break; + } +} + + uint32_t sed1520_device::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) { if (m_static_drive) diff --git a/src/devices/video/sed1520.h b/src/devices/video/sed1520.h index 5b7bdc1b4a1..be9acd32744 100644 --- a/src/devices/video/sed1520.h +++ b/src/devices/video/sed1520.h @@ -21,6 +21,7 @@ #define SED1520_UPDATE_CB(name) uint32_t name(bitmap_ind16 &bitmap, const rectangle &cliprect, bool lcd_on, uint8_t *dram, uint8_t start_line, uint8_t adc, uint8_t duty) #define SED1560_UPDATE_CB(name) uint32_t name(bitmap_ind16 &bitmap, const rectangle &cliprect, bool lcd_on, uint8_t *dram, uint8_t start_line, uint8_t adc, uint8_t duty, bool reverse, bool fill, uint8_t contrast, bool line_inv, uint8_t line_inv_num) #define EPL43102_UPDATE_CB(name) uint32_t name(bitmap_ind16 &bitmap, const rectangle &cliprect, bool lcd_on, uint8_t *dram, uint8_t start_line, uint8_t adc, uint8_t duty, bool reverse, bool fill, uint8_t contrast, bool line_inv, uint8_t line_inv_num) +#define NT7502_UPDATE_CB(name) uint32_t name(bitmap_ind16 &bitmap, const rectangle &cliprect, bool lcd_on, uint8_t *dram, uint8_t start_line, uint8_t adc, uint8_t duty, bool reverse, bool fill, uint8_t contrast, bool line_inv, uint8_t line_inv_num) // ======================> sed15xx_device_base @@ -153,9 +154,30 @@ protected: }; +// ======================> nt7502_device + +class nt7502_device : public sed1560_device +{ +public: + // construction/destruction + nt7502_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0); + + virtual void control_write(uint8_t data) override; + +protected: + // device-level overrides + virtual void device_start() override; + virtual void device_reset() override; + + // internal state + uint8_t m_last_command; +}; + + // device type definition DECLARE_DEVICE_TYPE(SED1520, sed1520_device) DECLARE_DEVICE_TYPE(SED1560, sed1560_device) DECLARE_DEVICE_TYPE(EPL43102, epl43102_device) +DECLARE_DEVICE_TYPE(NT7502, nt7502_device) #endif // MAME_VIDEO_SED1520_H diff --git a/src/mame/benesse/challenge_gear.cpp b/src/mame/benesse/challenge_gear.cpp index 18051c7fcc5..86ed48f7268 100644 --- a/src/mame/benesse/challenge_gear.cpp +++ b/src/mame/benesse/challenge_gear.cpp @@ -4,6 +4,7 @@ #include "emu.h" #include "cpu/olms66k/msm665xx.h" +#include "video/sed1520.h" #include "bus/generic/slot.h" #include "bus/generic/carts.h" @@ -54,12 +55,13 @@ public: protected: virtual void machine_start() override ATTR_COLD; virtual void machine_reset() override ATTR_COLD; - virtual void video_start() override ATTR_COLD; private: - uint32_t screen_update_challenge_gear(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); DECLARE_DEVICE_IMAGE_LOAD_MEMBER(cart_load); + NT7502_UPDATE_CB(lcd_update); + void program_map(address_map &map) ATTR_COLD; + void data_map(address_map &map) ATTR_COLD; //required_device m_maincpu; required_device m_cart; @@ -76,12 +78,9 @@ DEVICE_IMAGE_LOAD_MEMBER( challenge_gear_state::cart_load ) return std::make_pair(std::error_condition(), std::string()); } -void challenge_gear_state::video_start() -{ -} - -uint32_t challenge_gear_state::screen_update_challenge_gear(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) +NT7502_UPDATE_CB( challenge_gear_state::lcd_update ) { + // TODO return 0; } @@ -90,6 +89,12 @@ void challenge_gear_state::program_map(address_map &map) map(0x00000, 0x7ffff).rom().region("maincpu", 0); } +void challenge_gear_state::data_map(address_map &map) +{ + map.global_mask(0xffff); + map(0x8000, 0x8001).rw("lcdc", FUNC(nt7502_device::read), FUNC(nt7502_device::write)); +} + static INPUT_PORTS_START( challenge_gear ) INPUT_PORTS_END @@ -107,14 +112,20 @@ void challenge_gear_state::challenge_gear(machine_config &config) /* basic machine hardware */ msm665xx_device &maincpu(MSM66573(config, "maincpu", 14'000'000)); maincpu.set_addrmap(AS_PROGRAM, &challenge_gear_state::program_map); + maincpu.set_addrmap(AS_DATA, &challenge_gear_state::data_map); - /* video hardware - this is incorrect, but it does have a screen */ + /* video hardware */ screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_LCD)); screen.set_refresh_hz(60); screen.set_vblank_time(ATTOSECONDS_IN_USEC(0)); - screen.set_size(256, 256); - screen.set_visarea(0, 256-1, 16, 256-16-1); - screen.set_screen_update(FUNC(challenge_gear_state::screen_update_challenge_gear)); + screen.set_size(100, 64); + screen.set_visarea_full(); + screen.set_palette("palette"); + screen.set_screen_update("lcdc", FUNC(nt7502_device::screen_update)); + + PALETTE(config, "palette", palette_device::MONOCHROME_INVERTED); + + NT7502(config, "lcdc").set_screen_update_cb(FUNC(challenge_gear_state::lcd_update)); generic_cartslot_device &cartslot(GENERIC_CARTSLOT(config, "cartslot", generic_plain_slot, "challenge_gear_cart", "bin")); cartslot.set_device_load(FUNC(challenge_gear_state::cart_load));