hd44102: add intermediate render buffer

This commit is contained in:
hap 2022-09-19 14:51:02 +02:00
parent 0055a33e81
commit 9d08937608
10 changed files with 126 additions and 145 deletions

View File

@ -30,7 +30,7 @@ license:CC0
</software>
<software name="pokemahj">
<description>Pokekon Mahjongg</description>
<description>Pokekon Mahjong</description>
<year>1984</year>
<publisher>Epoch</publisher>
<info name="serial" value="3" />
@ -54,7 +54,7 @@ license:CC0
</software>
<software name="sokoban">
<description>Soukoban - Store Keepers</description>
<description>Sokoban - Store Keepers</description>
<year>1985</year>
<publisher>Epoch</publisher>
<info name="serial" value="5" />

View File

@ -2,7 +2,17 @@
// copyright-holders:Curt Coder
/**********************************************************************
HD44102 Dot Matrix Liquid Crystal Graphic Display Column Driver emulation
HD44102 Dot Matrix Liquid Crystal Graphic Display Column Driver
Not to be confused with HD44100.
Includes 4*50*8bit RAM.
TODO:
- properly emulate CS pins if needed? (there's 3, for enabling read and/or write)
- add BS pin when needed (4-bit mode)
- busy flag
- reset state
- what happens if Y address is invalid? (set to > 49)
**********************************************************************/
@ -26,7 +36,6 @@
#define CONTROL_X_ADDRESS_MASK 0xc0
#define CONTROL_DISPLAY_START_PAGE 0x3e
#define STATUS_BUSY 0x80 /* not supported */
#define STATUS_COUNT_UP 0x40
#define STATUS_DISPLAY_OFF 0x20
@ -37,28 +46,6 @@
DEFINE_DEVICE_TYPE(HD44102, hd44102_device, "hd44102", "Hitachi HD44102 LCD Controller")
//**************************************************************************
// INLINE HELPERS
//**************************************************************************
//-------------------------------------------------
// count_up_or_down -
//-------------------------------------------------
inline void hd44102_device::count_up_or_down()
{
if (m_status & STATUS_COUNT_UP)
{
if (++m_y > 49) m_y = 0;
}
else
{
if (--m_y < 0) m_y = 49;
}
}
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
@ -67,13 +54,10 @@ inline void hd44102_device::count_up_or_down()
// hd44102_device - constructor
//-------------------------------------------------
hd44102_device::hd44102_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, HD44102, tag, owner, clock),
device_video_interface(mconfig, *this),
m_cs2(0),
m_page(0),
m_x(0),
m_y(0)
hd44102_device::hd44102_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
device_t(mconfig, HD44102, tag, owner, clock),
m_sx(0),
m_sy(0)
{
}
@ -84,17 +68,26 @@ hd44102_device::hd44102_device(const machine_config &mconfig, const char *tag, d
void hd44102_device::device_start()
{
// zerofill
m_status = 0;
m_output = 0;
m_page = 0;
m_x = 0;
m_y = 0;
memset(m_ram, 0, sizeof(m_ram));
memset(m_render_buf, 0, sizeof(m_render_buf));
// register for state saving
save_item(NAME(m_ram[0]));
save_item(NAME(m_ram[1]));
save_item(NAME(m_ram[2]));
save_item(NAME(m_ram[3]));
save_item(NAME(m_ram));
save_item(NAME(m_render_buf));
save_item(NAME(m_status));
save_item(NAME(m_output));
save_item(NAME(m_cs2));
save_item(NAME(m_page));
save_item(NAME(m_x));
save_item(NAME(m_y));
save_item(NAME(m_sx));
save_item(NAME(m_sy));
}
@ -112,16 +105,9 @@ void hd44102_device::device_reset()
// read - register read
//-------------------------------------------------
uint8_t hd44102_device::read(offs_t offset)
u8 hd44102_device::read(offs_t offset)
{
uint8_t data = 0;
if (m_cs2)
{
data = (offset & 0x01) ? data_r() : status_r();
}
return data;
return (offset & 0x01) ? data_r() : status_r();
}
@ -129,12 +115,9 @@ uint8_t hd44102_device::read(offs_t offset)
// write - register write
//-------------------------------------------------
void hd44102_device::write(offs_t offset, uint8_t data)
void hd44102_device::write(offs_t offset, u8 data)
{
if (m_cs2)
{
(offset & 0x01) ? data_w(data) : control_w(data);
}
(offset & 0x01) ? data_w(data) : control_w(data);
}
@ -142,7 +125,7 @@ void hd44102_device::write(offs_t offset, uint8_t data)
// status_r - status read
//-------------------------------------------------
uint8_t hd44102_device::status_r()
u8 hd44102_device::status_r()
{
return m_status;
}
@ -152,7 +135,7 @@ uint8_t hd44102_device::status_r()
// control_w - control write
//-------------------------------------------------
void hd44102_device::control_w(uint8_t data)
void hd44102_device::control_w(u8 data)
{
if (m_status & STATUS_BUSY) return;
@ -209,16 +192,31 @@ void hd44102_device::control_w(uint8_t data)
}
//-------------------------------------------------
// count_up_or_down -
//-------------------------------------------------
void hd44102_device::count_up_or_down()
{
if (m_status & STATUS_COUNT_UP)
{
if (++m_y > 49) m_y = 0;
}
else
{
if (--m_y < 0) m_y = 49;
}
}
//-------------------------------------------------
// data_r - data read
//-------------------------------------------------
uint8_t hd44102_device::data_r()
u8 hd44102_device::data_r()
{
uint8_t data = m_output;
u8 data = m_output;
m_output = m_ram[m_x][m_y];
count_up_or_down();
return data;
@ -229,21 +227,36 @@ uint8_t hd44102_device::data_r()
// data_w - data write
//-------------------------------------------------
void hd44102_device::data_w(uint8_t data)
void hd44102_device::data_w(u8 data)
{
m_ram[m_x][m_y] = data;
count_up_or_down();
}
//-------------------------------------------------
// cs2_w - chip select 2 write
// render - render the pixels
//-------------------------------------------------
void hd44102_device::cs2_w(int state)
const u8 *hd44102_device::render()
{
m_cs2 = state;
memset(m_render_buf, 0, sizeof(m_render_buf));
if (!(m_status & STATUS_DISPLAY_OFF))
{
for (int x = 0; x < 50; x++)
{
int z = m_page << 3;
for (int y = 0; y < 32; y++)
{
m_render_buf[z * 50 + x] = BIT(m_ram[z >> 3][x], z & 7);
z = (z + 1) & 0x1f;
}
}
}
return m_render_buf;
}
@ -251,29 +264,21 @@ void hd44102_device::cs2_w(int state)
// update_screen - update screen
//-------------------------------------------------
uint32_t hd44102_device::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
u32 hd44102_device::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
for (int y = 0; y < 50; y++)
const u8 *src = render();
for (int x = 0; x < 50; x++)
{
int z = m_page << 3;
for (int x = 0; x < 32; x++)
for (int y = 0; y < 32; y++)
{
uint8_t data = m_ram[z / 8][y];
int sy = m_sy + z;
int sx = m_sx + y;
int sx = m_sx + x;
int sy = m_sy + y;
if (cliprect.contains(sx, sy))
{
int color = (m_status & STATUS_DISPLAY_OFF) ? 0 : BIT(data, z % 8);
bitmap.pix(sy, sx) = color;
}
z++;
z %= 32;
bitmap.pix(sy, sx) = src[y * 50 + x];
}
}
return 0;
}

View File

@ -2,7 +2,7 @@
// copyright-holders:Curt Coder
/**********************************************************************
HD44102 Dot Matrix Liquid Crystal Graphic Display Column Driver emulation
HD44102 Dot Matrix Liquid Crystal Graphic Display Column Driver
**********************************************************************/
@ -18,30 +18,20 @@
// ======================> hd44102_device
class hd44102_device : public device_t,
public device_video_interface
class hd44102_device : public device_t
{
public:
// construction/destruction
template <typename T>
hd44102_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, T &&screen_tag, int sx, int sy)
:hd44102_device(mconfig, tag, owner, clock)
{
set_screen(std::forward<T>(screen_tag));
set_offsets(sx, sy);
}
hd44102_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
hd44102_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0);
// inline configuration helpers
void set_offsets(int sx, int sy) { m_sx = sx; m_sy = sy; }
void set_screen_offsets(int sx, int sy) { m_sx = sx; m_sy = sy; } // when using screen_update
uint8_t read(offs_t offset);
void write(offs_t offset, uint8_t data);
u8 read(offs_t offset);
void write(offs_t offset, u8 data);
void cs2_w(int state);
uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
const u8 *render();
u32 screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
protected:
// device-level overrides
@ -49,23 +39,22 @@ protected:
virtual void device_reset() override;
private:
uint8_t status_r();
void control_w(uint8_t data);
u8 status_r();
void control_w(u8 data);
uint8_t data_r();
void data_w(uint8_t data);
void count_up_or_down();
u8 data_r();
void data_w(u8 data);
inline void count_up_or_down();
u8 m_ram[4][50]; // display memory
u8 m_render_buf[32 * 50]; // intermediate pixel buffer
uint8_t m_ram[4][50]; // display memory
u8 m_status; // status register
u8 m_output; // output register
uint8_t m_status; // status register
uint8_t m_output; // output register
int m_cs2; // chip select
int m_page; // display start page
int m_x; // X address
int m_y; // Y address
u8 m_page; // display start page
int m_x; // X address
int m_y; // Y address
int m_sx;
int m_sy;

View File

@ -2,12 +2,12 @@
// copyright-holders:Sandro Ronco
/***************************************************************************
Hitachi HD44780 LCD controller
Hitachi HD44780 LCD controller
TODO:
- dump internal CGROM
- emulate osc pin, determine video timings and busy flag duration from it,
and if possible, remove m_busy_factor
TODO:
- dump internal CGROM
- emulate osc pin, determine video timings and busy flag duration from it,
and if possible, remove m_busy_factor
***************************************************************************/

View File

@ -2,7 +2,7 @@
// copyright-holders:Sandro Ronco
/***************************************************************************
Hitachi HD44780 LCD controller
Hitachi HD44780 LCD controller
***************************************************************************/

View File

@ -273,7 +273,7 @@ void as12_state::felega(machine_config &config)
ROM Definitions
******************************************************************************/
ROM_START( feleg ) // model 6085
ROM_START( feleg ) // model 6085, serial 613623xx
ROM_REGION( 0x10000, "maincpu", 0 )
ROM_LOAD("feleg.8000", 0x8000, 0x2000, CRC(e9df31e8) SHA1(31c52bb8f75580c82093eb950959c1bc294189a8) ) // TMM2764, no label
ROM_LOAD("feleg.c000", 0xc000, 0x1000, CRC(bed9c84b) SHA1(c12f39765b054d2ad81f747e698715ad4246806d) ) // "

View File

@ -25,7 +25,7 @@ Known releases:
I presume it's an anonymous Hong Kong production. Most of the games too,
they have no copyright/company info in them. Some of the later games have
a copyright by Bon Treasure (a Hong Kong company that's also involved with
Watara SuperVision), so perhaps it's them.
Watara Supervision), so perhaps it's them.
TODO:
- does port B do anything?

View File

@ -69,6 +69,7 @@ on Joerg Woerner's datamath.org: http://www.datamath.org/IC_List.htm
@MP0905B TMS0970 1977, Parker Brothers Codename Sector
*MP0027 TMS1000 1977, Texas Instruments OEM melody chip (used in eg. Chromatronics Chroma-Chime)
*MP0057 TMS1000 1978, APH Student Speech+ (same ROM contents as TSI Speech+?)
*MP0121 TMS1000 1979, Waddingtons Compute-A-Tune
@MP0154 TMS1000 1979, Fonas 2 Player Baseball
@MP0158 TMS1000 1979, Entex Soccer (6003)
@MP0163 TMS1000 1979, A-One LSI Match Number/LJN Electronic Concentration

View File

@ -534,7 +534,8 @@ uint8_t kc85_state::lcd_r(offs_t offset)
uint8_t data = 0;
for (uint8_t i = 0; i < 10; i++)
data |= m_lcdc[i]->read(offset);
if (BIT(m_keylatch, i))
data |= m_lcdc[i]->read(offset);
return data;
}
@ -542,7 +543,8 @@ uint8_t kc85_state::lcd_r(offs_t offset)
void kc85_state::lcd_w(offs_t offset, uint8_t data)
{
for (uint8_t i = 0; i < 10; i++)
m_lcdc[i]->write(offset, data);
if (BIT(m_keylatch, i))
m_lcdc[i]->write(offset, data);
}
/* Memory Maps */
@ -949,12 +951,8 @@ void kc85_state::i8155_pa_w(uint8_t data)
*/
/* keyboard */
m_keylatch = (m_keylatch & 0x100) | data;
/* LCD */
for (uint8_t i = 0; i < 8; i++)
m_lcdc[i]->cs2_w(BIT(data, i));
/* LCD, keyboard */
m_keylatch = (m_keylatch & 0x300) | data;
/* RTC */
m_rtc->c0_w(BIT(data, 0));
@ -981,12 +979,8 @@ void kc85_state::i8155_pb_w(uint8_t data)
*/
/* keyboard */
m_keylatch = (BIT(data, 0) << 8) | (m_keylatch & 0xff);
/* LCD */
m_lcdc[8]->cs2_w(BIT(data, 0));
m_lcdc[9]->cs2_w(BIT(data, 1));
/* LCD, keyboard */
m_keylatch = (data << 8 & 0x300) | (m_keylatch & 0xff);
/* beeper */
m_buzzer = BIT(data, 2);

View File

@ -45,21 +45,13 @@ void kc85_state::kc85_video(machine_config &config)
screen.set_refresh_hz(44);
screen.set_screen_update(FUNC(kc85_state::screen_update));
screen.set_size(240, 64);
screen.set_visarea(0, 240-1, 0, 64-1);
screen.set_visarea_full();
screen.set_palette("palette");
PALETTE(config, "palette", FUNC(kc85_state::kc85_palette), 2);
HD44102(config, m_lcdc[0], 0, SCREEN_TAG, 0, 0);
HD44102(config, m_lcdc[1], 0, SCREEN_TAG, 50, 0);
HD44102(config, m_lcdc[2], 0, SCREEN_TAG, 100, 0);
HD44102(config, m_lcdc[3], 0, SCREEN_TAG, 150, 0);
HD44102(config, m_lcdc[4], 0, SCREEN_TAG, 200, 0);
HD44102(config, m_lcdc[5], 0, SCREEN_TAG, 0, 32);
HD44102(config, m_lcdc[6], 0, SCREEN_TAG, 50, 32);
HD44102(config, m_lcdc[7], 0, SCREEN_TAG, 100, 32);
HD44102(config, m_lcdc[8], 0, SCREEN_TAG, 150, 32);
HD44102(config, m_lcdc[9], 0, SCREEN_TAG, 200, 32);
for (int i = 0; i < 10; i++)
HD44102(config, m_lcdc[i]).set_screen_offsets((i % 5) * 50, (i / 5) * 32);
// MCFG_HD44103_MASTER_ADD("m11", SCREEN_TAG, CAP_P(18), RES_K(100), HD44103_FS_HIGH, HD44103_DUTY_1_32)
// MCFG_HD44103_SLAVE_ADD( "m12", "m11", SCREEN_TAG, HD44103_FS_HIGH, HD44103_DUTY_1_32)
@ -71,7 +63,7 @@ void tandy200_state::tandy200_video(machine_config &config)
screen.set_refresh_hz(80);
screen.set_screen_update(FUNC(tandy200_state::screen_update));
screen.set_size(240, 128);
screen.set_visarea(0, 240-1, 0, 128-1);
screen.set_visarea_full();
screen.set_palette("palette");
PALETTE(config, "palette", FUNC(tandy200_state::tandy200_palette), 2);