summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/machine/i3002.h
blob: 8fea81bad3ce87317ac2757a542f587a39ead632 (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:F. Ulivi
/**********************************************************************

    i3002.h

    Intel 3002 Central Processing Element

**********************************************************************
             _____   _____
      I0/  1|*    \_/     |28 VCC
      I1/  2|             |27 F2
      K0/  3|             |26 F1
      K1/  4|             |25 F0
        X  5|             |24 F3
        Y  6|             |23 ED/
      CO/  7|             |22 M0/
      RO/  8|             |21 M1/
      LI/  9|  DIP28      |20 D1/
      CI/ 10|  i3002      |19 D0/
      EA/ 11|             |18 CLK
      A1/ 12|             |17 F4
      A0/ 13|             |16 F5
      GND 14|_____________|15 F6

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

#ifndef MAME_MACHINE_I3002_H
#define MAME_MACHINE_I3002_H

#pragma once

class i3002_device : public device_t
{
public:
	i3002_device(const machine_config &mconfig , const char *tag , device_t *owner , uint32_t clock = 0);

	// Output callbacks
	template <typename... T> void set_co_w_cb(T &&... args) { m_co_handler.set(std::forward<T>(args)...); }
	template <typename... T> void set_ro_w_cb(T &&... args) { m_ro_handler.set(std::forward<T>(args)...); }

	// Input bus callbacks
	template <typename... T> void set_ibus_r_cb(T &&... args) { m_ibus_handler.set(std::forward<T>(args)...); }
	template <typename... T> void set_mbus_r_cb(T &&... args) { m_mbus_handler.set(std::forward<T>(args)...); }

	// Width of bit-slice
	static constexpr unsigned SLICE_SIZE = 2;

	// Mask of significant bits
	static constexpr uint8_t WORD_MASK = ((1U << SLICE_SIZE) - 1);

	// Registers
	enum : unsigned {
		  REG_R0,
		  REG_R1,
		  REG_R2,
		  REG_R3,
		  REG_R4,
		  REG_R5,
		  REG_R6,
		  REG_R7,
		  REG_R8,
		  REG_R9,
		  REG_T,
		  REG_AC,
		  REG_MAR,
		  REG_COUNT
	};

	static const char *reg_name(unsigned reg_idx);

	// Decode function code into function group, register group and register index
	static void decode_fc(uint8_t fc , uint8_t& fg , uint8_t& rg , unsigned& reg);

	// Set function code (7 bits) and K-bus (2 bits)
	void fc_kbus_w(uint8_t fc , uint8_t k);

	// Write Carry Input
	DECLARE_WRITE_LINE_MEMBER(ci_w) { m_ci = state; }

	// Write Left Input
	DECLARE_WRITE_LINE_MEMBER(li_w) { m_li = state; }

	// Read Carry Output
	DECLARE_READ_LINE_MEMBER(co_r) const { return m_co; }

	// Read Right Output
	DECLARE_READ_LINE_MEMBER(ro_r) const { return m_ro; }

	// Read output buses
	uint8_t abus_r() const { return m_reg[ REG_MAR ]; }
	uint8_t dbus_r() const { return m_reg[ REG_AC ]; }

	// Clock pulse
	DECLARE_WRITE_LINE_MEMBER(clk_w);

	// Compute RO if FC is the code of right-shift op (and return true)
	// Return false in all other cases
	bool update_ro();

	// Access to registers (debugging only: registers are not directly accessible in the real hw)
	const uint8_t& get_reg(unsigned idx) const { return m_reg[ idx ]; }
	uint8_t& get_reg(unsigned idx) { return m_reg[ idx ]; }

protected:
	virtual void device_start() override;

private:
	device_delegate<void (int)> m_co_handler;
	device_delegate<void (int)> m_ro_handler;
	device_delegate<uint8_t ()> m_ibus_handler;
	device_delegate<uint8_t ()> m_mbus_handler;

	uint8_t m_reg[ REG_COUNT ];
	uint8_t m_fc;
	uint8_t m_kbus;
	bool m_ci;
	bool m_li;
	bool m_co;
	bool m_ro;

	void update();
	void set_co(bool co);
	void set_ro(bool ro);
};

// device type definition
DECLARE_DEVICE_TYPE(I3002, i3002_device)

#endif /* MAME_MACHINE_I3002_H */