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