mirror of
https://github.com/holub/mame
synced 2025-04-24 17:30:55 +03:00
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.
This commit is contained in:
parent
feea04e882
commit
c1f4b4600a
@ -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 ++;
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
};
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user