summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/machine/znmcu.cpp
blob: 1b21d956e1bb27b8951f1d34dc35c44e797eb547 (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
107
108
109
110
111
112
113
114
115
// license:BSD-3-Clause
// copyright-holders:smf
#include "emu.h"
#include "znmcu.h"

DEFINE_DEVICE_TYPE(ZNMCU, znmcu_device, "znmcu", "Sony ZN MCU")

znmcu_device::znmcu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
	device_t(mconfig, ZNMCU, tag, owner, clock),
	m_dsw_handler(*this),
	m_analog1_handler(*this),
	m_analog2_handler(*this),
	m_dataout_handler(*this),
	m_dsr_handler(*this),
	m_select(1),
	m_clk(1),
	m_bit(0),
	m_byte(0),
	m_databytes(0)
{
}

void znmcu_device::device_start()
{
	m_dsw_handler.resolve_safe(0xff);
	m_analog1_handler.resolve_safe(0xff);
	m_analog2_handler.resolve_safe(0xff);
	m_dataout_handler.resolve_safe();
	m_dsr_handler.resolve_safe();

	m_mcu_timer = timer_alloc(0);

	m_dataout_handler(1);
	m_dsr_handler(1);

	save_item(NAME(m_select));
	save_item(NAME(m_clk));
	save_item(NAME(m_bit));
	save_item(NAME(m_byte));
	save_item(NAME(m_databytes));
	save_item(NAME(m_send));

	memset(m_send, 0, sizeof(m_send));
}

WRITE_LINE_MEMBER(znmcu_device::write_select)
{
	if (m_select != state)
	{
		if (!state)
		{
			m_bit = 0;
			m_byte = 0;
			m_mcu_timer->adjust(attotime::from_usec(50), 0);
		}
		else
		{
			m_dataout_handler(1);
			m_dsr_handler(1);
			m_mcu_timer->adjust(attotime::never);
		}

		m_select = state;
	}
}

WRITE_LINE_MEMBER(znmcu_device::write_clock)
{
	if (m_clk != state)
	{
		if (!state && !m_select)
		{
			uint8_t data = 0;
			if (m_byte <= m_databytes && m_byte < MaxBytes)
			{
				data = m_send[m_byte];
			}

			int dataout = ((data >> m_bit) & 1);
			m_dataout_handler(dataout);

			m_bit++;
			if (m_bit == 8)
			{
				if (m_byte < m_databytes)
				{
					m_mcu_timer->adjust(attotime::from_usec(50), 0);
				}

				m_bit = 0;
				m_byte++;
			}
		}

		m_clk = state;
	}
}

void znmcu_device::device_timer(emu_timer &timer, device_timer_id tid, int param, void *ptr)
{
	m_dsr_handler(param);

	if (!param)
	{
		if (m_byte == 0)
		{
			m_databytes = 2;
			m_send[0] = (m_databytes << 4) | (m_dsw_handler() & 0xf);
			m_send[1] = m_analog1_handler();
			m_send[2] = m_analog2_handler();
		}

		m_mcu_timer->adjust(attotime::from_usec(5), 1);
	}
}