// license:BSD-3-Clause
// copyright-holders:Olivier Galibert
/***************************************************************************
SED1200
A LCD controller.
The D/F variants have a packaging difference (QFP80 vs. bare chip).
The A/B variants have an internal CGROM difference (jis
vs. european characters)
***************************************************************************/
#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")
ROM_START( sed1200x0a )
ROM_REGION( 0x800, "cgrom", 0 )
ROM_LOAD( "sed1200-a.bin", 0x000, 0x800, CRC(e8c28054) SHA1(086406eb74e9ed97b309d2a4bdedc567626e9a98))
ROM_END
ROM_START( sed1200x0b )
ROM_REGION( 0x800, "cgrom", 0 )
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)
{
}
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)
{
}
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)
{
}
const tiny_rom_entry *sed1200d0a_device::device_rom_region() const
{
return ROM_NAME(sed1200x0a);
}
const tiny_rom_entry *sed1200f0a_device::device_rom_region() const
{
return ROM_NAME(sed1200x0a);
}
const tiny_rom_entry *sed1200d0b_device::device_rom_region() const
{
return ROM_NAME(sed1200x0b);
}
const tiny_rom_entry *sed1200f0b_device::device_rom_region() const
{
return ROM_NAME(sed1200x0b);
}
void sed1200_device::device_start()
{
memset(cgram, 0, sizeof(cgram));
memset(ddram, 0, sizeof(ddram));
if(memregion("cgrom"))
cgrom = memregion("cgrom")->base();
else
cgrom = nullptr;
soft_reset();
}
void sed1200_device::soft_reset()
{
cursor_direction = false;
cursor_blinking = false;
cursor_full = false;
cursor_on = false;
display_on = false;
cursor_address = 0x00;
cgram_address = 0x00;
}
void sed1200_device::control_w(uint8_t data)
{
switch(data) {
case 0x04: case 0x05:
cursor_direction = data & 0x01;
break;
case 0x06: case 0x07:
cursor_step();
break;
case 0x08: case 0x09:
cursor_full = data & 0x01;
break;
case 0x0a: case 0x0b:
cursor_blinking = data & 0x01;
break;
case 0x0c: case 0x0d:
display_on = data & 0x01;
break;
case 0x0e: case 0x0f:
cursor_on = data & 0x01;
break;
case 0x10:
soft_reset();
break;
case 0x12: case 0x13:
break; // Number of lines selection
default:
if((data & 0xf0) == 0x20)
cgram_address = (data & 3)*8;
else if((data & 0xe0) == 0x40) {
cgram[cgram_address++] = 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;
}
break;
}
}
uint8_t sed1200_device::control_r()
{
return 0x00;
}
void sed1200_device::data_w(uint8_t data)
{
ddram[cursor_address] = data;
cursor_step();
}
void sed1200_device::cursor_step()
{
if(cursor_direction) {
if(cursor_address == 0 || cursor_address == 10)
cursor_address += 9;
else
cursor_address --;
} else {
if(cursor_address == 9 || cursor_address == 19)
cursor_address -= 9;
else
cursor_address ++;
}
}
const uint8_t *sed1200_device::render()
{
memset(render_buf, 0, 20*8);
if(!display_on)
return render_buf;
for(int i=0; i<20; i++) {
uint8_t c = ddram[i];
if(c < 4)
memcpy(render_buf + 8*i, cgram + 8*c, 8);
else if(cgrom)
memcpy(render_buf + 8*i, cgrom + 8*c, 8);
}
if(cursor_on && (!cursor_blinking || (machine().time().as_ticks(2) & 1))) {
if(cursor_full)
for(int i=0; i<8; i++)
render_buf[cursor_address*8+i] ^= 0x1f;
else
render_buf[cursor_address*8+7] ^= 0x1f;
}
return render_buf;
}