hlcd0515: couple of accuracy improvements (nw)

This commit is contained in:
hap 2017-01-23 23:44:39 +01:00
parent 194460c362
commit 5830838f26
3 changed files with 91 additions and 53 deletions

View File

@ -3,10 +3,12 @@
/* /*
Hughes HLCD 0515/0569 LCD Driver Hughes HLCD 0515/0569 LCD Driver
0515: 25 columns(also size of buffer/ram)
0569: 24 columns, no DATA OUT pin, display blank has no effect
TODO: TODO:
- What's the difference between 0515 and 0569? For now assume 0569 is a cost-reduced chip, - read mode is untested
lacking the data out pin.
- MAME bitmap update callback when needed - MAME bitmap update callback when needed
*/ */
@ -21,20 +23,19 @@ const device_type HLCD0569 = &device_creator<hlcd0569_device>;
// constructor // constructor
//------------------------------------------------- //-------------------------------------------------
hlcd0515_device::hlcd0515_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) hlcd0515_device::hlcd0515_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, u32 clock, u8 colmax, const char *shortname, const char *source)
: device_t(mconfig, HLCD0515, "HLCD 0515 LCD Driver", tag, owner, clock, "hlcd0515", __FILE__), : device_t(mconfig, type, name, tag, owner, clock, shortname, source),
m_write_cols(*this), m_write_data(*this) m_colmax(colmax), m_write_cols(*this), m_write_data(*this)
{ {
} }
hlcd0515_device::hlcd0515_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, u32 clock, const char *shortname, const char *source) hlcd0515_device::hlcd0515_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: device_t(mconfig, type, name, tag, owner, clock, shortname, source), : hlcd0515_device(mconfig, HLCD0515, "HLCD 0515 LCD Driver", tag, owner, clock, 25, "hlcd0515", __FILE__)
m_write_cols(*this), m_write_data(*this)
{ {
} }
hlcd0569_device::hlcd0569_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) hlcd0569_device::hlcd0569_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: hlcd0515_device(mconfig, HLCD0569, "HLCD 0569 LCD Driver", tag, owner, clock, "hlcd0569", __FILE__) : hlcd0515_device(mconfig, HLCD0569, "HLCD 0569 LCD Driver", tag, owner, clock, 24, "hlcd0569", __FILE__)
{ {
} }
@ -64,6 +65,7 @@ void hlcd0515_device::device_start()
m_rowmax = 0; m_rowmax = 0;
m_rowout = 0; m_rowout = 0;
m_rowsel = 0; m_rowsel = 0;
m_buffer = 0;
memset(m_ram, 0, sizeof(m_ram)); memset(m_ram, 0, sizeof(m_ram));
// register for savestates // register for savestates
@ -76,6 +78,7 @@ void hlcd0515_device::device_start()
save_item(NAME(m_rowmax)); save_item(NAME(m_rowmax));
save_item(NAME(m_rowout)); save_item(NAME(m_rowout));
save_item(NAME(m_rowsel)); save_item(NAME(m_rowsel));
save_item(NAME(m_buffer));
save_item(NAME(m_ram)); save_item(NAME(m_ram));
} }
@ -101,7 +104,7 @@ void hlcd0515_device::device_timer(emu_timer &timer, device_timer_id id, int par
m_rowout = 0; m_rowout = 0;
// write to COL/ROW pins // write to COL/ROW pins
m_write_cols(m_rowout, m_blank ? m_ram[m_rowout] : 0, 0xffffffff); m_write_cols(m_rowout, m_blank ? 0 : m_ram[m_rowout], 0xffffffff);
m_rowout++; m_rowout++;
} }
@ -111,68 +114,92 @@ void hlcd0515_device::device_timer(emu_timer &timer, device_timer_id id, int par
// handlers // handlers
//------------------------------------------------- //-------------------------------------------------
WRITE_LINE_MEMBER(hlcd0515_device::write_cs) void hlcd0515_device::set_control()
{ {
state = (state) ? 1 : 0; // clock 0,1,2: row select
m_rowsel = m_control >> 2 & 7;
// start serial sequence on falling edge // clock 3(,4): initialize
if (!state && m_cs) if (m_control & 2)
{ {
m_count = 0; m_rowmax = m_rowsel;
m_control = 0; m_blank = bool(~m_control & 1);
} }
m_cs = state; // clock 4: read/write mode
if (m_control & 1)
m_buffer = m_ram[m_rowsel];
} }
void hlcd0569_device::set_control()
{
hlcd0515_device::set_control();
m_blank = false; // 0569 doesn't support display blanking
}
void hlcd0515_device::clock_data(int col)
{
if (m_control & 1)
{
if (col < m_colmax)
m_buffer <<= 1;
m_write_data(m_buffer >> m_colmax & 1);
}
else
{
if (col < m_colmax)
m_buffer >>= 1;
// always write last column
u32 mask = 1 << (m_colmax - 1);
m_buffer = (m_buffer & ~mask) | (m_data ? mask : 0);
}
}
WRITE_LINE_MEMBER(hlcd0515_device::write_clock) WRITE_LINE_MEMBER(hlcd0515_device::write_clock)
{ {
state = (state) ? 1 : 0; state = (state) ? 1 : 0;
// clock/shift data on falling edge // clock/shift data on falling edge
if (!m_cs && m_count < 30 && !state && m_clock) if (!m_cs && !state && m_clock)
{ {
if (m_count < 5) if (m_count < 5)
{ {
// 5-bit mode/control // 5-bit mode/control
m_control = m_control << 1 | m_data; m_control = m_control << 1 | m_data;
if (m_count == 4) if (m_count == 4)
{ set_control();
// clock 0,1,2: row select
// clock 3: initialize
// clock 4: read/write
m_rowsel = m_control >> 2 & 7;
if (m_control & 2)
{
m_rowmax = m_rowsel;
m_blank = bool(m_control & 1);
}
}
} }
else else
{ clock_data(m_count - 5);
if (m_control & 1)
{ if (m_count < (m_colmax + 5))
// read data, output m_count++;
m_write_data(m_ram[m_rowsel] >> (m_count - 5) & 1);
}
else
{
// write data
u32 mask = 1 << (m_count - 5);
m_ram[m_rowsel] = (m_ram[m_rowsel] & ~mask) | (m_data ? mask : 0);
}
}
m_count++;
} }
m_clock = state; m_clock = state;
} }
WRITE_LINE_MEMBER(hlcd0515_device::write_data)
WRITE_LINE_MEMBER(hlcd0515_device::write_cs)
{ {
m_data = (state) ? 1 : 0; state = (state) ? 1 : 0;
// finish serial sequence on rising edge
if (state && !m_cs)
{
// transfer to ram
if (~m_control & 1)
m_ram[m_rowsel] = m_buffer;
m_count = 0;
m_control = 0;
m_buffer = 0;
}
m_cs = state;
} }

View File

@ -16,7 +16,7 @@
#define MCFG_HLCD0515_WRITE_COLS_CB(_devcb) \ #define MCFG_HLCD0515_WRITE_COLS_CB(_devcb) \
hlcd0515_device::set_write_cols_callback(*device, DEVCB_##_devcb); hlcd0515_device::set_write_cols_callback(*device, DEVCB_##_devcb);
// DATA OUT pin // DATA OUT pin, don't use on HLCD0569
#define MCFG_HLCD0515_WRITE_DATA_CB(_devcb) \ #define MCFG_HLCD0515_WRITE_DATA_CB(_devcb) \
hlcd0515_device::set_write_data_callback(*device, DEVCB_##_devcb); hlcd0515_device::set_write_data_callback(*device, DEVCB_##_devcb);
@ -46,6 +46,8 @@
COL11 19 | | 22 COL13 COL11 19 | | 22 COL13
GND 20 |___________| 21 COL12 GND 20 |___________| 21 COL12
HLCD 0569 doesn't have DATA OUT, instead it has what seems like OSC OUT on pin 34.
OSC is tied to a capacitor, the result frequency is 50000 * cap(in uF), eg. 0.01uF cap = 500Hz. OSC is tied to a capacitor, the result frequency is 50000 * cap(in uF), eg. 0.01uF cap = 500Hz.
Internally, this is divided by 2, and by number of rows to get display refresh frequency. Internally, this is divided by 2, and by number of rows to get display refresh frequency.
*/ */
@ -54,15 +56,15 @@ class hlcd0515_device : public device_t
{ {
public: public:
hlcd0515_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); hlcd0515_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
hlcd0515_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, u32 clock, const char *shortname, const char *source); hlcd0515_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, u32 clock, u8 colmax, const char *shortname, const char *source);
// static configuration helpers // static configuration helpers
template<class _Object> static devcb_base &set_write_cols_callback(device_t &device, _Object object) { return downcast<hlcd0515_device &>(device).m_write_cols.set_callback(object); } template<class _Object> static devcb_base &set_write_cols_callback(device_t &device, _Object object) { return downcast<hlcd0515_device &>(device).m_write_cols.set_callback(object); }
template<class _Object> static devcb_base &set_write_data_callback(device_t &device, _Object object) { return downcast<hlcd0515_device &>(device).m_write_data.set_callback(object); } template<class _Object> static devcb_base &set_write_data_callback(device_t &device, _Object object) { return downcast<hlcd0515_device &>(device).m_write_data.set_callback(object); }
DECLARE_WRITE_LINE_MEMBER(write_cs);
DECLARE_WRITE_LINE_MEMBER(write_clock); DECLARE_WRITE_LINE_MEMBER(write_clock);
DECLARE_WRITE_LINE_MEMBER(write_data); DECLARE_WRITE_LINE_MEMBER(write_cs);
DECLARE_WRITE_LINE_MEMBER(write_data) { m_data = (state) ? 1 : 0; }
protected: protected:
// device-level overrides // device-level overrides
@ -70,6 +72,11 @@ protected:
virtual void device_reset() override; virtual void device_reset() override;
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override; virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
virtual void set_control();
void clock_data(int col);
u8 m_colmax; // number of column pins
int m_cs; // input pin state int m_cs; // input pin state
int m_clock; // " int m_clock; // "
int m_data; // " int m_data; // "
@ -79,7 +86,8 @@ protected:
u8 m_rowmax; // number of rows output by lcd (max 8) u8 m_rowmax; // number of rows output by lcd (max 8)
u8 m_rowout; // current row for lcd output u8 m_rowout; // current row for lcd output
u8 m_rowsel; // current row for data in/out u8 m_rowsel; // current row for data in/out
u32 m_ram[8]; // 8x25bit ram u32 m_buffer; // data in/out shift register
u32 m_ram[8]; // internal lcd ram, 8 rows
emu_timer *m_lcd_timer; emu_timer *m_lcd_timer;
@ -93,6 +101,9 @@ class hlcd0569_device : public hlcd0515_device
{ {
public: public:
hlcd0569_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); hlcd0569_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
protected:
virtual void set_control() override;
}; };

View File

@ -19,6 +19,7 @@
@CP0904A TMS0970 1977, Milton Bradley Comp IV @CP0904A TMS0970 1977, Milton Bradley Comp IV
@MP0905B TMS0970 1977, Parker Brothers Codename Sector @MP0905B TMS0970 1977, Parker Brothers Codename Sector
*MP0057 TMS1000 1978, APH Student Speech+ (same ROM contents as TSI Speech+?) *MP0057 TMS1000 1978, APH Student Speech+ (same ROM contents as TSI Speech+?)
*MP0154 TMS1000 1979, Fonas 2 Player Baseball
@MP0158 TMS1000 1979, Entex Soccer (6003) @MP0158 TMS1000 1979, Entex Soccer (6003)
@MP0163 TMS1000 1979, A-One LSI Match Number/LJN Electronic Concentration @MP0163 TMS1000 1979, A-One LSI Match Number/LJN Electronic Concentration
@MP0168 TMS1000 1979, Conic Multisport/Tandy Sports Arena (model 60-2158) @MP0168 TMS1000 1979, Conic Multisport/Tandy Sports Arena (model 60-2158)
@ -4823,7 +4824,6 @@ WRITE16_MEMBER(comp4_state::write_o)
// O0: leds common // O0: leds common
// other bits: N/C // other bits: N/C
m_o = data; m_o = data;
display_matrix(11, 1, m_r, m_o);
} }
READ8_MEMBER(comp4_state::read_k) READ8_MEMBER(comp4_state::read_k)