1 // license:BSD-3-Clause
2 // copyright-holders: F. Ulivi
3 /*********************************************************************
4
5 82939.cpp
6
7 82939 module (RS232 interface)
8
9 Thanks to Tim Nye & Everett Kaser for dumping the 8049 ROM
10
11 Main reference for this module is:
12 HP 82939-90001, jun 81, HP82939A Serial Interface - Installation
13 and Theory of operation manual
14
15 *********************************************************************/
16
17 #include "emu.h"
18 #include "82939.h"
19 #include "coreutil.h"
20
21 // Debugging
22 #define VERBOSE 0
23 #include "logmacro.h"
24
25 // Bit manipulation
26 namespace {
BIT_MASK(unsigned n)27 template<typename T> constexpr T BIT_MASK(unsigned n)
28 {
29 return (T)1U << n;
30 }
31
BIT_SET(T & w,unsigned n)32 template<typename T> void BIT_SET(T& w , unsigned n)
33 {
34 w |= BIT_MASK<T>(n);
35 }
36 }
37
hp82939_io_card_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)38 hp82939_io_card_device::hp82939_io_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
39 : device_t(mconfig , HP82939_IO_CARD , tag , owner , clock),
40 device_hp80_io_interface(mconfig, *this),
41 m_cpu(*this , "cpu"),
42 m_translator(*this , "xlator"),
43 m_rs232(*this , "rs232"),
44 m_uart(*this , "uart"),
45 m_sw12(*this , "sw12")
46 {
47 }
48
~hp82939_io_card_device()49 hp82939_io_card_device::~hp82939_io_card_device()
50 {
51 }
52
install_read_write_handlers(address_space & space,uint16_t base_addr)53 void hp82939_io_card_device::install_read_write_handlers(address_space& space , uint16_t base_addr)
54 {
55 space.install_readwrite_handler(base_addr, base_addr + 1, read8sm_delegate(*m_translator, FUNC(hp_1mb5_device::cpu_r)), write8sm_delegate(*m_translator, FUNC(hp_1mb5_device::cpu_w)));
56 }
57
inten()58 void hp82939_io_card_device::inten()
59 {
60 m_translator->inten();
61 }
62
clear_service()63 void hp82939_io_card_device::clear_service()
64 {
65 m_translator->clear_service();
66 }
67
68 static INPUT_PORTS_START(hp82939_port)
69 PORT_HP80_IO_SC(10)
70 PORT_START("sw12")
71 PORT_DIPNAME(0x40 , 0 , "Auto Handshake")
72 PORT_DIPLOCATION("S1:1")
73 PORT_DIPSETTING(0x00 , "Ignore")
DEF_STR(On)74 PORT_DIPSETTING(0x40 , DEF_STR(On))
75 PORT_DIPNAME(0x20 , 0 , "Parity tx")
76 PORT_DIPLOCATION("S2:1")
77 PORT_DIPSETTING(0x00 , DEF_STR(Off))
78 PORT_DIPSETTING(0x20 , DEF_STR(On))
79 PORT_DIPNAME(0x10 , 0 , "Parity")
80 PORT_DIPLOCATION("S2:2")
81 PORT_DIPSETTING(0x00 , "Odd")
82 PORT_DIPSETTING(0x10 , "Even")
83 PORT_DIPNAME(0x08 , 0x08 , "Parity enable")
84 PORT_DIPLOCATION("S2:3")
85 PORT_DIPSETTING(0x00 , DEF_STR(Off))
86 PORT_DIPSETTING(0x08 , DEF_STR(On))
87 PORT_DIPNAME(0x04 , 0 , "Stop bits")
88 PORT_DIPLOCATION("S2:4")
89 PORT_DIPSETTING(0x00 , "1")
90 PORT_DIPSETTING(0x04 , "2")
91 PORT_DIPNAME(0x03 , 0x02 , "Character size")
92 PORT_DIPLOCATION("S2:5,6")
93 PORT_DIPSETTING(0x00 , "5")
94 PORT_DIPSETTING(0x01 , "6")
95 PORT_DIPSETTING(0x02 , "7")
96 PORT_DIPSETTING(0x03 , "8")
97 PORT_DIPNAME(0x780 , 0x300 , "Baud rate")
98 PORT_DIPLOCATION("S2:7,8,9,10")
99 PORT_DIPSETTING(0x000 , "50")
100 PORT_DIPSETTING(0x080 , "75")
101 PORT_DIPSETTING(0x100 , "110")
102 PORT_DIPSETTING(0x180 , "134.5")
103 PORT_DIPSETTING(0x200 , "150")
104 PORT_DIPSETTING(0x280 , "200")
105 PORT_DIPSETTING(0x300 , "300")
106 PORT_DIPSETTING(0x380 , "600")
107 PORT_DIPSETTING(0x400 , "1200")
108 PORT_DIPSETTING(0x480 , "1800")
109 PORT_DIPSETTING(0x500 , "2000")
110 PORT_DIPSETTING(0x580 , "2400")
111 PORT_DIPSETTING(0x600 , "3600")
112 PORT_DIPSETTING(0x680 , "4800")
113 PORT_DIPSETTING(0x700 , "7200")
114 PORT_DIPSETTING(0x780 , "9600")
115 INPUT_PORTS_END
116
117 ioport_constructor hp82939_io_card_device::device_input_ports() const
118 {
119 return INPUT_PORTS_NAME(hp82939_port);
120 }
121
device_start()122 void hp82939_io_card_device::device_start()
123 {
124 }
125
126 ROM_START(hp82939)
127 ROM_REGION(0x800 , "cpu" , 0)
128 ROM_LOAD("1820-2438.bin" , 0 , 0x800 , CRC(3a2f42a2) SHA1(0f6a70eb8981a8a87c7514ce8226ff1af3ac1668))
129 ROM_END
130
p1_r()131 uint8_t hp82939_io_card_device::p1_r()
132 {
133 uint8_t res = uint8_t(m_sw12->read() & 0x7f);
134
135 BIT_SET(res , 7);
136
137 return res;
138 }
139
p1_w(uint8_t data)140 void hp82939_io_card_device::p1_w(uint8_t data)
141 {
142 if (BIT(data , 7)) {
143 m_uart->reset();
144 }
145 }
146
p2_r()147 uint8_t hp82939_io_card_device::p2_r()
148 {
149 uint8_t res = uint8_t((m_sw12->read() >> 7) & 0xf);
150
151 if (m_rs232->cts_r()) {
152 BIT_SET(res , 4);
153 }
154 if (m_rs232->dsr_r()) {
155 BIT_SET(res , 5);
156 }
157 // RI always reads 1
158 BIT_SET(res , 6);
159 if (m_rs232->dcd_r()) {
160 BIT_SET(res , 7);
161 }
162
163 return res;
164 }
165
cpu_r(offs_t offset)166 uint8_t hp82939_io_card_device::cpu_r(offs_t offset)
167 {
168 if ((offset & 0x82) == 0x00) {
169 return m_translator->uc_r(offset & 1);
170 } else if ((offset & 0x83) == 0x82) {
171 return m_uart->ins8250_r((offset >> 2) & 7);
172 } else {
173 return 0xff;
174 }
175 }
176
cpu_w(offs_t offset,uint8_t data)177 void hp82939_io_card_device::cpu_w(offs_t offset, uint8_t data)
178 {
179 if ((offset & 0x82) == 0x00) {
180 m_translator->uc_w(offset & 1 , data);
181 } else if ((offset & 0x83) == 0x82) {
182 m_uart->ins8250_w((offset >> 2) & 7 , data);
183 }
184 }
185
cpu_io_map(address_map & map)186 void hp82939_io_card_device::cpu_io_map(address_map &map)
187 {
188 map.unmap_value_high();
189 map(0x00 , 0xff).rw(FUNC(hp82939_io_card_device::cpu_r) , FUNC(hp82939_io_card_device::cpu_w));
190 }
191
device_rom_region() const192 const tiny_rom_entry *hp82939_io_card_device::device_rom_region() const
193 {
194 return ROM_NAME(hp82939);
195 }
196
device_add_mconfig(machine_config & config)197 void hp82939_io_card_device::device_add_mconfig(machine_config &config)
198 {
199 I8049(config, m_cpu, XTAL(5'529'600));
200 m_cpu->set_addrmap(AS_IO, &hp82939_io_card_device::cpu_io_map);
201 m_cpu->t1_in_cb().set("xlator", FUNC(hp_1mb5_device::int_r));
202 m_cpu->set_t0_clk_cb("uart" , FUNC(device_t::set_unscaled_clock_int));
203 m_cpu->p1_in_cb().set(FUNC(hp82939_io_card_device::p1_r));
204 m_cpu->p1_out_cb().set(FUNC(hp82939_io_card_device::p1_w));
205 m_cpu->p2_in_cb().set(FUNC(hp82939_io_card_device::p2_r));
206
207 HP_1MB5(config, m_translator, 0);
208 m_translator->irl_handler().set(FUNC(hp82939_io_card_device::irl_w));
209 m_translator->halt_handler().set(FUNC(hp82939_io_card_device::halt_w));
210 m_translator->reset_handler().set_inputline(m_cpu , INPUT_LINE_RESET);
211
212 RS232_PORT(config, m_rs232, default_rs232_devices, nullptr);
213
214 INS8250(config , m_uart , 0);
215 m_uart->out_int_callback().set_inputline(m_cpu , MCS48_INPUT_IRQ);
216 m_uart->out_tx_callback().set(m_rs232 , FUNC(rs232_port_device::write_txd));
217 m_uart->out_dtr_callback().set(m_rs232 , FUNC(rs232_port_device::write_dtr));
218 m_uart->out_rts_callback().set(m_rs232 , FUNC(rs232_port_device::write_rts));
219 m_uart->out_out1_callback().set(m_rs232 , FUNC(rs232_port_device::write_spds));
220
221 m_rs232->rxd_handler().set(m_uart , FUNC(ins8250_device::rx_w));
222 m_rs232->dcd_handler().set(m_uart , FUNC(ins8250_device::dcd_w));
223 m_rs232->dsr_handler().set(m_uart , FUNC(ins8250_device::dsr_w));
224 m_rs232->cts_handler().set(m_uart , FUNC(ins8250_device::cts_w));
225 }
226
227 // device type definition
228 DEFINE_DEVICE_TYPE(HP82939_IO_CARD, hp82939_io_card_device, "hp82939", "HP82939 card")
229