summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/machine/msm6253.cpp
blob: 025e7d0d2d68530ec5ebbc2834372ddf923dc3f7 (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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
// license:BSD-3-Clause
// copyright-holders: AJR
/**********************************************************************

    OKI MSM6253 8-Bit 4-Channel A/D Converter

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

#include "emu.h"
#include "machine/msm6253.h"

//**************************************************************************
//  GLOBAL VARIABLES
//**************************************************************************

const device_type MSM6253 = device_creator<msm6253_device>;

//**************************************************************************
//  DEVICE DEFINITION
//**************************************************************************

//-------------------------------------------------
//  msm6253_device - constructor
//-------------------------------------------------

msm6253_device::msm6253_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
	: device_t(mconfig, MSM6253, "MSM6253 A/D Converter", tag, owner, clock, "msm6253", __FILE__),
		m_analog_ports(*this, {finder_base::DUMMY_TAG, finder_base::DUMMY_TAG, finder_base::DUMMY_TAG, finder_base::DUMMY_TAG}),
		m_shift_register(0)
{
	m_analog_input_cb[0] = analog_port_read_delegate(FUNC(msm6253_device::port_read<0>), this);
	m_analog_input_cb[1] = analog_port_read_delegate(FUNC(msm6253_device::port_read<1>), this);
	m_analog_input_cb[2] = analog_port_read_delegate(FUNC(msm6253_device::port_read<2>), this);
	m_analog_input_cb[3] = analog_port_read_delegate(FUNC(msm6253_device::port_read<3>), this);
}

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

void msm6253_device::device_start()
{
	for (int port = 0; port < 4; port++)
	{
		// resolve each callback
		m_analog_input_cb[port].bind_relative_to(*owner());

		// ensure that any configured ports truly are analog
		if (m_analog_ports[port].found())
		{
			for (ioport_field &field : m_analog_ports[port]->fields())
				if (!field.is_analog() && field.type() != IPT_UNKNOWN && field.type() != IPT_UNUSED)
					throw emu_fatalerror("Port %s is not an analog port\n", m_analog_ports[port]->tag());
		}
	}

	// save our state
	save_item(NAME(m_shift_register));
}

//-------------------------------------------------
//  port_read - helper to read configured ports
//-------------------------------------------------

template<int port>
ioport_value msm6253_device::port_read()
{
	if (m_analog_ports[port].found())
		return m_analog_ports[port]->read();

	logerror("%s: Read from unassigned IN%d\n", machine().describe_context(), port);
	return 0xff;
}

//-------------------------------------------------
//  address_w - write from address bus to select
//  one of four internal latches
//-------------------------------------------------

WRITE8_MEMBER(msm6253_device::address_w)
{
	// fill the shift register from the internal A/D latch
	m_shift_register = m_analog_input_cb[offset & 3]();
}

//-------------------------------------------------
//  select_w - write D0/D1 to address latch
//-------------------------------------------------

WRITE8_MEMBER(msm6253_device::select_w)
{
	// fill the shift register from the internal A/D latch
	m_shift_register = m_analog_input_cb[data & 3]();
}

//-------------------------------------------------
//  shift_out - MSB-first serial data output
//-------------------------------------------------

bool msm6253_device::shift_out()
{
	// capture the shifted bit
	bool msb = BIT(m_shift_register, 7);

	// shift the bit out, with zero coming in on the other end
	m_shift_register <<= 1;

	// return the bit
	return msb;
}

//-------------------------------------------------
//  d0_r - shift data bit out to D0
//-------------------------------------------------

READ8_MEMBER(msm6253_device::d0_r)
{
	// offset is ignored
	return shift_out() | (space.unmap() & 0xfe);
}

//-------------------------------------------------
//  d7_r - shift data bit out to D7
//-------------------------------------------------

READ8_MEMBER(msm6253_device::d7_r)
{
	// offset is ignored
	return (shift_out() << 7) | (space.unmap() & 0x7f);
}