summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/video/hd61603.cpp
blob: 49a21cc779b773db328fde0f58a006b9e5ad3a94 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
// license:BSD-3-Clause
// copyright-holders:hap
/*

Hitachi HD61603 LCD Driver
64 segment outputs, no duty cycle

TODO:
- OSC pin (input is resistor)
- SB pin, halts internal clock
- SYNC pin for chip cascading
- READY pin

*/

#include "emu.h"
#include "video/hd61603.h"


DEFINE_DEVICE_TYPE(HD61603, hd61603_device, "hd61603", "Hitachi HD61603 LCD Driver")

//-------------------------------------------------
//  constructor
//-------------------------------------------------

hd61603_device::hd61603_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
	device_t(mconfig, HD61603, tag, owner, clock),
	m_write_segs(*this)
{ }


//-------------------------------------------------
//  device_start - device-specific startup
//-------------------------------------------------

void hd61603_device::device_start()
{
	// resolve callbacks
	m_write_segs.resolve_safe();

	// zerofill
	m_blank = 0;
	m_count = 0;
	m_data = 0;
	m_ram = 0;

	// register for savestates
	save_item(NAME(m_blank));
	save_item(NAME(m_count));
	save_item(NAME(m_data));
	save_item(NAME(m_ram));
}

void hd61603_device::device_reset()
{
	m_count = 0;
}


//-------------------------------------------------
//  handlers
//-------------------------------------------------

void hd61603_device::data_w(u8 data)
{
	// 1-byte nop command
	if (m_count == 0 && (data & 0xc) == 0xc)
		return;

	// each command is 4 writes
	m_data = (m_data << 4) | (data & 0xf);
	m_count = (m_count + 1) & 3;

	if (m_count == 0)
	{
		switch (m_data >> 14 & 3)
		{
			// write byte
			case 0:
			{
				u8 shift = (m_data >> 8 & 7) * 8;
				u8 digit = bitswap<8>(m_data & 0xff, 0,1,2,3,4,5,6,7);
				m_ram = (m_ram & ~(u64(0xff) << shift)) | u64(digit) << shift;
				break;
			}

			// write bit
			case 1:
			{
				u64 mask = u64(1) << (m_data & 0x3f);
				m_ram = (m_ram & ~mask) | ((m_data & 0x2000) ? mask : 0);
				break;
			}

			// set mode
			case 2:
				m_blank = BIT(m_data, 2);
				break;

			default:
				break;
		}

		m_write_segs(0, m_blank ? 0 : m_ram);
	}
}