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:LGPL-2.1+
// copyright-holders:Angelo Salese, R. Belmont, Juergen Buchmueller, Sandro Ronco
/**************************************************************************************************
Acorn RISC Machine Input/Output Controller (IOC)
**************************************************************************************************/
#ifndef MAME_MACHINE_ACORN_IOC_H
#define MAME_MACHINE_ACORN_IOC_H
#pragma once
#include "diserial.h"
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
// ======================> acorn_ioc_device
class acorn_ioc_device : public device_t, public device_serial_interface
{
public:
acorn_ioc_device(const machine_config &mconfig, const char *tag, device_t *owner, const XTAL &clock);
template <unsigned N> auto peripheral_r() { static_assert(N >= 1 && N <= 7); return m_peripherals_r[N - 1].bind(); }
template <unsigned N> auto peripheral_w() { static_assert(N >= 1 && N <= 7); return m_peripherals_w[N - 1].bind(); }
template <unsigned N> auto gpio_r() { static_assert(N <= 5); return m_giop_r[N].bind(); }
template <unsigned N> auto gpio_w() { static_assert(N <= 5); return m_giop_w[N].bind(); }
auto irq_w() { return m_irq_w.bind(); }
auto fiq_w() { return m_fiq_w.bind(); }
auto baud_w() { return m_baud_w.bind(); }
auto kout_w() { return m_kout_w.bind(); }
void map(address_map &map);
uint32_t registers_r(offs_t offset, uint32_t mem_mask = ~0);
void registers_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
template<unsigned N> uint32_t periph_r(offs_t offset, uint32_t mem_mask = ~0) { return m_peripherals_r[N - 1](offset, mem_mask); }
template<unsigned N> void periph_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0) { m_peripherals_w[N - 1](offset, data, mem_mask); }
DECLARE_WRITE_LINE_MEMBER(il0_w) { change_interrupt(IRQ_STATUS_B, 0x01, state); change_interrupt(FIQ_STATUS, 0x40, state); }
DECLARE_WRITE_LINE_MEMBER(il1_w) { change_interrupt(IRQ_STATUS_B, 0x02, state); }
DECLARE_WRITE_LINE_MEMBER(il2_w) { change_interrupt(IRQ_STATUS_B, 0x04, state); }
DECLARE_WRITE_LINE_MEMBER(il3_w) { change_interrupt(IRQ_STATUS_B, 0x08, state); }
DECLARE_WRITE_LINE_MEMBER(il4_w) { change_interrupt(IRQ_STATUS_B, 0x10, state); }
DECLARE_WRITE_LINE_MEMBER(il5_w) { change_interrupt(IRQ_STATUS_B, 0x20, state); }
DECLARE_WRITE_LINE_MEMBER(il6_w) { change_interrupt(IRQ_STATUS_A, 0x01, state); }
DECLARE_WRITE_LINE_MEMBER(il7_w) { change_interrupt(IRQ_STATUS_A, 0x02, state); }
DECLARE_WRITE_LINE_MEMBER(fh0_w) { change_interrupt(FIQ_STATUS , 0x01, state); }
DECLARE_WRITE_LINE_MEMBER(fh1_w) { change_interrupt(FIQ_STATUS , 0x02, state); }
DECLARE_WRITE_LINE_MEMBER(fl_w) { change_interrupt(FIQ_STATUS , 0x04, !state); }
DECLARE_WRITE_LINE_MEMBER(por_w) { if (state) change_interrupt(IRQ_STATUS_A, 0x10, state); }
DECLARE_WRITE_LINE_MEMBER(kin_w) { rx_w(state); }
DECLARE_WRITE_LINE_MEMBER(if_w);
DECLARE_WRITE_LINE_MEMBER(ir_w);
protected:
// device-level overrides
virtual void device_resolve_objects() override;
virtual void device_start() override;
virtual void device_reset() override;
// device_serial_interface overrides
virtual void tra_callback() override;
virtual void tra_complete() override;
virtual void rcv_complete() override;
private:
void update_interrups();
void change_interrupt(int reg, uint8_t mask, int state);
void set_timer(int tmr);
void latch_timer_cnt(int tmr);
TIMER_CALLBACK_MEMBER(timer_tick);
enum // registers
{
CONTROL = 0x00 / 4,
KART = 0x04 / 4,
IRQ_STATUS_A = 0x10 / 4,
IRQ_REQUEST_A = 0x14 / 4,
IRQ_MASK_A = 0x18 / 4,
IRQ_STATUS_B = 0x20 / 4,
IRQ_REQUEST_B = 0x24 / 4,
IRQ_MASK_B = 0x28 / 4,
FIQ_STATUS = 0x30 / 4,
FIQ_REQUEST = 0x34 / 4,
FIQ_MASK = 0x38 / 4,
T0_LATCH_LO = 0x40 / 4,
T0_LATCH_HI = 0x44 / 4,
T0_GO = 0x48 / 4,
T0_LATCH = 0x4c / 4,
T1_LATCH_LO = 0x50 / 4,
T1_LATCH_HI = 0x54 / 4,
T1_GO = 0x58 / 4,
T1_LATCH = 0x5c / 4,
T2_LATCH_LO = 0x60 / 4,
T2_LATCH_HI = 0x64 / 4,
T2_GO = 0x68 / 4,
T2_LATCH = 0x6c / 4,
T3_LATCH_LO = 0x70 / 4,
T3_LATCH_HI = 0x74 / 4,
T3_GO = 0x78 / 4,
T3_LATCH = 0x7c / 4,
};
devcb_read32::array<7> m_peripherals_r;
devcb_write32::array<7> m_peripherals_w;
devcb_read_line::array<6> m_giop_r;
devcb_write_line::array<6> m_giop_w;
devcb_write_line m_irq_w;
devcb_write_line m_fiq_w;
devcb_write_line m_kout_w;
devcb_write_line m_baud_w;
emu_timer * m_timers[4];
int m_ir;
int m_if;
int m_baud;
uint32_t m_timercnt[4];
uint32_t m_timerout[4];
uint8_t m_regs[0x20];
};
// device type definition
DECLARE_DEVICE_TYPE(ACORN_IOC, acorn_ioc_device)
#endif // MAME_MACHINE_ACORN_IOC_H
|