Add Novatek NT7502 LCD Driver as SED1560 variant

This commit is contained in:
AJR 2024-11-02 08:46:21 -04:00
parent 74a0d801f8
commit e19fc2e326
3 changed files with 111 additions and 12 deletions

View file

@ -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)

View file

@ -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

View file

@ -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<cpu_device> m_maincpu;
required_device<generic_slot_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));