summaryrefslogblamecommitdiffstatshomepage
path: root/src/devices/video/msm6222b.cpp
blob: ebcbfea24fe92e3638eeacd9b8fccf7a18f3bafe (plain) (tree)
1
2
3
4
5
6
7
8
9
10

                                     







                                                                              




                                                                            

                                                                                                   





                                                                                                                   



                                                                                                                                                                            
 

 
                                                                                                                   
                                                             
 
                                            

 
                                                                                                                         
                                                                
 
                               
                                        

 
                                                                   





                                     













                                           
                                             

                
                                                               











































                                                   
                                    



                          
                                          
















































































                                                                        
                                                            





                                                 
                                        







                                                 
                                                  

                                                                                                                      

                                                                               























                                                                               
// license:BSD-3-Clause
// copyright-holders:Olivier Galibert
/***************************************************************************

    MSM6222B

    A somewhat hd44780-compatible LCD controller.

    The -01 variant has a fixed cgrom, the other variants are mask-programmed.

***************************************************************************/

#include "emu.h"
#include "msm6222b.h"

DEFINE_DEVICE_TYPE(MSM6222B,    msm6222b_device,    "msm6222b",   "Oki MSM6222B-xx LCD Controller")
DEFINE_DEVICE_TYPE(MSM6222B_01, msm6222b_01_device, "msm6222b01", "Oki MSM6222B-01 LCD Controller")

ROM_START( msm6222b_01 )
	ROM_REGION( 0x1000, "cgrom", 0 )
	ROM_LOAD( "msm6222b-01.bin", 0x0000, 0x1000, CRC(8ffa8521) SHA1(e108b520e6d20459a7bbd5958bbfa1d551a690bd) )
ROM_END

msm6222b_device::msm6222b_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
	device_t(mconfig, type, tag, owner, clock),
	m_cgrom(*this, finder_base::DUMMY_TAG),
	cursor_direction(false), cursor_blinking(false), two_line(false), shift_on_write(false), double_height(false), cursor_on(false), display_on(false), adc(0), shift(0)
{
}

msm6222b_device::msm6222b_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
	msm6222b_device(mconfig, MSM6222B, tag, owner, clock)
{
	m_cgrom.set_tag(*this, DEVICE_SELF);
}

msm6222b_01_device::msm6222b_01_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
	msm6222b_device(mconfig, MSM6222B_01, tag, owner, clock)
{
	// load the fixed cgrom
	m_cgrom.set_tag(*this, "cgrom");
}

const tiny_rom_entry *msm6222b_01_device::device_rom_region() const
{
	return ROM_NAME(msm6222b_01);
}

void msm6222b_device::device_start()
{
	memset(cgram, 0, sizeof(cgram));
	memset(ddram, 0x20, sizeof(ddram));

	cursor_direction = true;
	cursor_blinking = false;
	display_on = false;
	two_line = false;
	cursor_on = false;
	shift_on_write = false;
	double_height = false;
	adc = 0x00;
	shift = 0;
}

void msm6222b_device::control_w(uint8_t data)
{
	int cmd;
	for(cmd = 7; cmd >= 0 && !(data & (1<<cmd)); cmd--) {};
	switch(cmd) {
	case 0:
		memset(ddram, 0x20, sizeof(ddram));
		adc = 0x00;
		break;

	case 1:
		adc = 0x00;
		shift = 0x00;
		break;
	case 2:
		shift_on_write = data & 1;
		cursor_direction = data & 2;
		break;

	case 3:
		display_on = data & 4;
		cursor_on = data & 2;
		cursor_blinking = data & 1;
		break;

	case 4:
		if(data & 8)
			shift_step(data & 4);
		else
			cursor_step(data & 4);
		break;

	case 5:
		two_line = data & 8;
		double_height = (data & 0xc) == 4;
		// Bit 4 is 4bits/8bits data access
		break;

	case 6:
		adc = data & 0x3f;
		break;

	case 7:
		adc = data; // Bit 7 is set
		break;
	}
}

uint8_t msm6222b_device::control_r()
{
	return adc & 0x7f;
}

void msm6222b_device::data_w(uint8_t data)
{
	if(adc & 0x80) {
		int adr = adc & 0x7f;
		if(two_line) {
			if((adr >= 40 && adr < 64) || adr >= 64+40)
				adr = -1;
			if(adr >= 64)
				adr += 40-64;
		} else {
			if(adr >= 80)
				adr = -1;
		}
		if(adr != -1) {
			ddram[adr] = data;
			if(shift_on_write)
				shift_step(cursor_direction);
			else
				cursor_step(cursor_direction);
		}
	} else {
		if(adc < 8*8) {
			cgram[adc] = data;
			cursor_step(cursor_direction);
		}
	}
}

void msm6222b_device::cursor_step(bool direction)
{
	if(direction) {
		if(adc & 0x80) {
			if(two_line && adc == (0x80|39))
				adc = 0x80|64;
			else if(two_line && adc == (0x80|(64+39)))
				adc = 0x80;
			else if((!two_line) && adc == (0x80|79))
				adc = 0x80;
			else
				adc++;
		} else {
			if(adc == 8*8-1)
				adc = 0x00;
			else
				adc++;
		}
	} else {
		if(adc & 0x80) {
			if(adc == 0x80)
				adc = two_line ? 0x80|(64+39) : 0x80|79;
			else if(two_line && adc == (0x80|64))
				adc = 0x80|39;
			else
				adc--;
		} else {
			if(adc == 0x00)
				adc = 8*8-1;
			else
				adc--;
		}
	}
}

void msm6222b_device::shift_step(bool direction)
{
	if(direction) {
		if(shift == 79)
			shift = 0;
		else
			shift++;
	} else {
		if(shift == 0)
			shift = 79;
		else
			shift--;
	}
}

bool msm6222b_device::blink_on() const
{
	if(!cursor_blinking)
		return false;
	uint64_t clocks = machine().time().as_ticks(250000);
	if(double_height)
		return clocks % 281600 >= 140800;
	else
		return clocks % 204800 >= 102400;
}

const uint8_t *msm6222b_device::render()
{
	memset(render_buf, 0, 80*16);
	if(!display_on)
		return render_buf;

	int char_height = double_height ? 11 : 8;

	for(int i=0; i<80; i++) {
		uint8_t c = ddram[(i+shift) % 80];
		if(c < 16)
			memcpy(render_buf + 16*i, double_height ? cgram + 8*(c & 6) : cgram + 8*(c & 7), char_height);
		else if (m_cgrom.found())
			memcpy(render_buf + 16*i, &m_cgrom[16*c], char_height);
	}

	if(cursor_on) {
		int cpos = adc & 0x7f;
		if(two_line) {
			if((cpos >= 40 && cpos < 64) || cpos >= 64+40)
				cpos = -1;
			else if(cpos >= 64)
				cpos += 40-64;
		} else {
			if(cpos >= 80)
				cpos = -1;
		}
		if(cpos != -1) {
			cpos = (cpos + shift) % 80;
			render_buf[cpos*16 + (double_height ? 10 : 7)] |= 0x1f;
			if(blink_on())
				for(int i=0; i<char_height; i++)
					render_buf[cpos*16 + i] ^= 0x1f;
		}
	}

	return render_buf;
}