1 // license:BSD-3-Clause
2 // copyright-holders:Curt Coder
3 /**********************************************************************
4 
5     CMD Turbo232 RS-232 cartridge emulation
6 
7 **********************************************************************/
8 
9 /*
10 
11     http://ar.c64.org/wiki/Turbo232_Programming.txt
12 
13 */
14 
15 #include "emu.h"
16 #include "turbo232.h"
17 
18 
19 
20 //**************************************************************************
21 //  MACROS/CONSTANTS
22 //**************************************************************************
23 
24 #define MOS6551_TAG     "mos6551"
25 #define RS232_TAG       "rs232"
26 
27 
28 
29 //**************************************************************************
30 //  DEVICE DEFINITIONS
31 //**************************************************************************
32 
33 DEFINE_DEVICE_TYPE(C64_TURBO232, c64_turbo232_cartridge_device, "c64_turbo232", "C64 Turbo232 cartridge")
34 
35 
36 //-------------------------------------------------
37 //  device_add_mconfig - add device configuration
38 //-------------------------------------------------
39 
device_add_mconfig(machine_config & config)40 void c64_turbo232_cartridge_device::device_add_mconfig(machine_config &config)
41 {
42 	MOS6551(config, m_acia, 0);
43 	m_acia->set_xtal(3.6864_MHz_XTAL);
44 	m_acia->irq_handler().set(FUNC(c64_turbo232_cartridge_device::acia_irq_w));
45 	m_acia->txd_handler().set(RS232_TAG, FUNC(rs232_port_device::write_txd));
46 
47 	rs232_port_device &rs232(RS232_PORT(config, RS232_TAG, default_rs232_devices, nullptr));
48 	rs232.rxd_handler().set(m_acia, FUNC(mos6551_device::write_rxd));
49 	rs232.dcd_handler().set(m_acia, FUNC(mos6551_device::write_dcd));
50 	rs232.dsr_handler().set(m_acia, FUNC(mos6551_device::write_dsr));
51 	rs232.cts_handler().set(m_acia, FUNC(mos6551_device::write_cts));
52 }
53 
54 
55 //-------------------------------------------------
56 //  INPUT_PORTS( c64_turbo232 )
57 //-------------------------------------------------
58 
59 static INPUT_PORTS_START( c64_turbo232 )
60 	PORT_START("CS")
61 	PORT_DIPNAME( 0x03, 0x01, "Base Address" )
62 	PORT_DIPSETTING(    0x00, "$D700 (C128)" )
63 	PORT_DIPSETTING(    0x01, "$DE00" )
64 	PORT_DIPSETTING(    0x02, "$DF00" )
65 
66 	PORT_START("IRQ")
67 	PORT_DIPNAME( 0x01, 0x01, "Interrupt" )
68 	PORT_DIPSETTING(    0x00, "IRQ" )
69 	PORT_DIPSETTING(    0x01, "NMI" )
70 INPUT_PORTS_END
71 
72 
73 //-------------------------------------------------
74 //  input_ports - device-specific input ports
75 //-------------------------------------------------
76 
device_input_ports() const77 ioport_constructor c64_turbo232_cartridge_device::device_input_ports() const
78 {
79 	return INPUT_PORTS_NAME( c64_turbo232 );
80 }
81 
82 
83 
84 //**************************************************************************
85 //  LIVE DEVICE
86 //**************************************************************************
87 
88 //-------------------------------------------------
89 //  c64_turbo232_cartridge_device - constructor
90 //-------------------------------------------------
91 
c64_turbo232_cartridge_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)92 c64_turbo232_cartridge_device::c64_turbo232_cartridge_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
93 	device_t(mconfig, C64_TURBO232, tag, owner, clock),
94 	device_c64_expansion_card_interface(mconfig, *this),
95 	m_acia(*this, MOS6551_TAG),
96 	m_rs232(*this, RS232_TAG),
97 	m_io_cs(*this, "CS"),
98 	m_io_irq(*this, "IRQ"), m_cs(0), m_irq(0), m_es(0)
99 {
100 }
101 
102 
103 //-------------------------------------------------
104 //  device_start - device-specific startup
105 //-------------------------------------------------
106 
device_start()107 void c64_turbo232_cartridge_device::device_start()
108 {
109 }
110 
111 
112 //-------------------------------------------------
113 //  device_reset - device-specific reset
114 //-------------------------------------------------
115 
device_reset()116 void c64_turbo232_cartridge_device::device_reset()
117 {
118 	m_acia->reset();
119 
120 	m_cs = m_io_cs->read();
121 	m_irq = m_io_irq->read();
122 
123 	m_es = 0;
124 }
125 
126 
127 //-------------------------------------------------
128 //  c64_cd_r - cartridge data read
129 //-------------------------------------------------
130 
c64_cd_r(offs_t offset,uint8_t data,int sphi2,int ba,int roml,int romh,int io1,int io2)131 uint8_t c64_turbo232_cartridge_device::c64_cd_r(offs_t offset, uint8_t data, int sphi2, int ba, int roml, int romh, int io1, int io2)
132 {
133 	if (((m_cs == DE00) && !io1) || ((m_cs == DF00) && !io2) ||
134 		((m_cs == D700) && ((offset & 0xff00) == 0xd700)))
135 	{
136 		if (!(offset & 0xe0))
137 		{
138 			switch (offset & 0x07)
139 			{
140 			case 0: case 1: case 2: case 3:
141 				data = m_acia->read(offset & 0x03);
142 				break;
143 
144 			case 7:
145 				data = m_es;
146 			}
147 		}
148 	}
149 
150 	return data;
151 }
152 
153 
154 //-------------------------------------------------
155 //  c64_cd_w - cartridge data write
156 //-------------------------------------------------
157 
c64_cd_w(offs_t offset,uint8_t data,int sphi2,int ba,int roml,int romh,int io1,int io2)158 void c64_turbo232_cartridge_device::c64_cd_w(offs_t offset, uint8_t data, int sphi2, int ba, int roml, int romh, int io1, int io2)
159 {
160 	if (((m_cs == DE00) && !io1) || ((m_cs == DF00) && !io2) ||
161 		((m_cs == D700) && ((offset & 0xff00) == 0xd700)))
162 	{
163 		if (!(offset & 0xe0))
164 		{
165 			switch (offset & 0x07)
166 			{
167 			case 0: case 1: case 2:
168 				m_acia->write(offset & 0x03, data);
169 				break;
170 
171 			case 3:
172 				m_acia->write(offset & 0x03, data);
173 
174 				if (data & 0x0f)
175 					m_es &= ~ES_M;
176 				else
177 					m_es |= ES_M;
178 				break;
179 
180 			case 7:
181 				if (m_es & ES_M)
182 				{
183 					data = m_es;
184 
185 					switch (m_es & ES_S_MASK)
186 					{
187 					case ES_S_230400: m_acia->set_xtal(XTAL(3'686'400)); break;
188 					case ES_S_115200: m_acia->set_xtal(XTAL(3'686'400)/2); break;
189 					case ES_S_57600: m_acia->set_xtal(XTAL(3'686'400)/4); break;
190 					case ES_S_UNDEFINED: m_acia->set_xtal(0); break;
191 					}
192 				}
193 			}
194 		}
195 	}
196 }
197 
198 
199 //-------------------------------------------------
200 //  acia_irq_w -
201 //-------------------------------------------------
202 
WRITE_LINE_MEMBER(c64_turbo232_cartridge_device::acia_irq_w)203 WRITE_LINE_MEMBER( c64_turbo232_cartridge_device::acia_irq_w )
204 {
205 	switch (m_irq)
206 	{
207 	case IRQ: m_slot->irq_w(state); break;
208 	case NMI: m_slot->nmi_w(state); break;
209 	}
210 }
211