1 // license:BSD-3-Clause
2 // copyright-holders:smf
3 /*
4  * PlayStation Serial I/O emulator
5  *
6  * Copyright 2003-2011 smf
7  *
8  */
9 
10 #include "emu.h"
11 #include "sio.h"
12 
13 #define VERBOSE_LEVEL ( 0 )
14 
verboselog(device_t & device,int n_level,const char * s_fmt,...)15 static inline void ATTR_PRINTF(3,4) verboselog( device_t& device, int n_level, const char *s_fmt, ... )
16 {
17 	if( VERBOSE_LEVEL >= n_level )
18 	{
19 		va_list v;
20 		char buf[ 32768 ];
21 		va_start( v, s_fmt );
22 		vsprintf( buf, s_fmt, v );
23 		va_end( v );
24 		device.logerror( "%s: %s", device.machine().describe_context(), buf );
25 	}
26 }
27 
28 DEFINE_DEVICE_TYPE(PSX_SIO0, psxsio0_device, "psxsio0", "Sony PSX SIO-0")
29 DEFINE_DEVICE_TYPE(PSX_SIO1, psxsio1_device, "psxsio1", "Sony PSX SIO-1")
30 
psxsio0_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)31 psxsio0_device::psxsio0_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
32 	psxsio_device(mconfig, PSX_SIO0, tag, owner, clock)
33 {
34 }
35 
psxsio1_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)36 psxsio1_device::psxsio1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
37 	psxsio_device(mconfig, PSX_SIO1, tag, owner, clock)
38 {
39 }
40 
psxsio_device(const machine_config & mconfig,device_type type,const char * tag,device_t * owner,uint32_t clock)41 psxsio_device::psxsio_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
42 	device_t(mconfig, type, tag, owner, clock),
43 	m_status(SIO_STATUS_TX_EMPTY | SIO_STATUS_TX_RDY), m_mode(0), m_control(0), m_baud(0),
44 	m_rxd(1), m_tx_data(0), m_rx_data(0), m_tx_shift(0), m_rx_shift(0), m_tx_bits(0), m_rx_bits(0), m_timer(nullptr),
45 	m_irq_handler(*this),
46 	m_sck_handler(*this),
47 	m_txd_handler(*this),
48 	m_dtr_handler(*this),
49 	m_rts_handler(*this)
50 {
51 }
52 
device_post_load()53 void psxsio_device::device_post_load()
54 {
55 	sio_timer_adjust();
56 }
57 
device_start()58 void psxsio_device::device_start()
59 {
60 	m_irq_handler.resolve_safe();
61 	m_sck_handler.resolve_safe();
62 	m_txd_handler.resolve_safe();
63 	m_dtr_handler.resolve_safe();
64 	m_rts_handler.resolve_safe();
65 
66 	m_timer = timer_alloc( 0 );
67 	m_mode = 0;
68 	m_control = 0;
69 	m_baud = 0;
70 	m_rx_data = 0;
71 	m_tx_data = 0;
72 	m_rx_shift = 0;
73 	m_tx_shift = 0;
74 	m_rx_bits = 0;
75 	m_tx_bits = 0;
76 
77 	save_item( NAME( m_status ) );
78 	save_item( NAME( m_mode ) );
79 	save_item( NAME( m_control ) );
80 	save_item( NAME( m_baud ) );
81 	save_item( NAME( m_rxd ) );
82 	save_item( NAME( m_rx_data ) );
83 	save_item( NAME( m_tx_data ) );
84 	save_item( NAME( m_rx_shift ) );
85 	save_item( NAME( m_tx_shift ) );
86 	save_item( NAME( m_rx_bits ) );
87 	save_item( NAME( m_tx_bits ) );
88 }
89 
sio_interrupt()90 void psxsio_device::sio_interrupt()
91 {
92 	verboselog( *this, 1, "sio_interrupt( %s )\n", tag() );
93 	m_status |= SIO_STATUS_IRQ;
94 	m_irq_handler(1);
95 }
96 
sio_timer_adjust()97 void psxsio_device::sio_timer_adjust()
98 {
99 	attotime n_time;
100 
101 	if( ( m_status & SIO_STATUS_TX_EMPTY ) == 0 || m_tx_bits != 0 )
102 	{
103 		int n_prescaler;
104 
105 		switch( m_mode & 3 )
106 		{
107 		case 1:
108 			n_prescaler = 1;
109 			break;
110 		case 2:
111 			n_prescaler = 16;
112 			break;
113 		case 3:
114 			n_prescaler = 64;
115 			break;
116 		default:
117 			n_prescaler = 0;
118 			break;
119 		}
120 
121 		if( m_baud != 0 && n_prescaler != 0 )
122 		{
123 			n_time = attotime::from_hz(33868800) * (n_prescaler * m_baud);
124 			verboselog( *this, 2, "sio_timer_adjust( %s ) = %s ( %d x %d )\n", tag(), n_time.as_string(), n_prescaler, m_baud );
125 		}
126 		else
127 		{
128 			n_time = attotime::never;
129 			verboselog( *this, 0, "sio_timer_adjust( %s ) invalid baud rate ( %d x %d )\n", tag(), n_prescaler, m_baud );
130 		}
131 	}
132 	else
133 	{
134 		n_time = attotime::never;
135 		verboselog( *this, 2, "sio_timer_adjust( %s ) finished\n", tag() );
136 	}
137 
138 	m_timer->adjust( n_time );
139 }
140 
device_timer(emu_timer & timer,device_timer_id tid,int param,void * ptr)141 void psxsio_device::device_timer(emu_timer &timer, device_timer_id tid, int param, void *ptr)
142 {
143 	verboselog( *this, 2, "sio tick\n" );
144 
145 	if( m_tx_bits == 0 &&
146 		( m_control & SIO_CONTROL_TX_ENA ) != 0 &&
147 		( m_status & SIO_STATUS_TX_EMPTY ) == 0 )
148 	{
149 		m_tx_bits = 8;
150 		m_tx_shift = m_tx_data;
151 
152 		if( type() == PSX_SIO0 )
153 		{
154 			m_rx_bits = 8;
155 			m_rx_shift = 0;
156 		}
157 
158 		m_status |= SIO_STATUS_TX_EMPTY;
159 		m_status |= SIO_STATUS_TX_RDY;
160 	}
161 
162 	if( m_tx_bits != 0 )
163 	{
164 		if( type() == PSX_SIO0 )
165 		{
166 			m_sck_handler(0);
167 		}
168 
169 		m_txd_handler( m_tx_shift & 1 );
170 		m_tx_shift >>= 1;
171 		m_tx_bits--;
172 
173 		if( type() == PSX_SIO0 )
174 		{
175 			m_sck_handler(1);
176 		}
177 
178 		if( m_tx_bits == 0 &&
179 			( m_control & SIO_CONTROL_TX_IENA ) != 0 )
180 		{
181 			sio_interrupt();
182 		}
183 	}
184 
185 	if( m_rx_bits != 0 )
186 	{
187 		m_rx_shift = ( m_rx_shift >> 1 ) | ( m_rxd << 7 );
188 		m_rx_bits--;
189 
190 		if( m_rx_bits == 0 )
191 		{
192 			if( ( m_status & SIO_STATUS_RX_RDY ) != 0 )
193 			{
194 				m_status |= SIO_STATUS_OVERRUN;
195 			}
196 			else
197 			{
198 				m_rx_data = m_rx_shift;
199 				m_status |= SIO_STATUS_RX_RDY;
200 			}
201 
202 			if( ( m_control & SIO_CONTROL_RX_IENA ) != 0 )
203 			{
204 				sio_interrupt();
205 			}
206 		}
207 	}
208 
209 	sio_timer_adjust();
210 }
211 
write(offs_t offset,uint32_t data,uint32_t mem_mask)212 void psxsio_device::write(offs_t offset, uint32_t data, uint32_t mem_mask)
213 {
214 	switch( offset % 4 )
215 	{
216 	case 0:
217 		verboselog( *this, 1, "psx_sio_w %s data %02x (%08x)\n", tag(), data, mem_mask );
218 		m_tx_data = data;
219 		m_status &= ~( SIO_STATUS_TX_RDY );
220 		m_status &= ~( SIO_STATUS_TX_EMPTY );
221 		sio_timer_adjust();
222 		break;
223 	case 1:
224 		verboselog( *this, 0, "psx_sio_w( %08x, %08x, %08x )\n", offset, data, mem_mask );
225 		break;
226 	case 2:
227 		if( ACCESSING_BITS_0_15 )
228 		{
229 			m_mode = data & 0xffff;
230 			verboselog( *this, 1, "psx_sio_w %s mode %04x\n", tag(), data & 0xffff );
231 		}
232 		if( ACCESSING_BITS_16_31 )
233 		{
234 			verboselog( *this, 1, "psx_sio_w %s control %04x\n", tag(), data >> 16 );
235 			m_control = data >> 16;
236 
237 			if( ( m_control & SIO_CONTROL_RESET ) != 0 )
238 			{
239 				verboselog( *this, 1, "psx_sio_w reset\n" );
240 				m_status |= SIO_STATUS_TX_EMPTY | SIO_STATUS_TX_RDY;
241 				m_status &= ~( SIO_STATUS_RX_RDY | SIO_STATUS_OVERRUN | SIO_STATUS_IRQ );
242 				m_irq_handler(0);
243 
244 				// toggle DTR to reset controllers, Star Ocean 2, at least, requires it
245 				// the precise mechanism of the reset is unknown
246 				// maybe it's related to the bottom 2 bits of control which are usually set
247 				m_dtr_handler(0);
248 				m_dtr_handler(1);
249 
250 				m_tx_bits = 0;
251 				m_rx_bits = 0;
252 				m_txd_handler(1);
253 			}
254 			if( ( m_control & SIO_CONTROL_IACK ) != 0 )
255 			{
256 				verboselog( *this, 1, "psx_sio_w iack\n" );
257 				m_status &= ~( SIO_STATUS_IRQ );
258 				m_control &= ~( SIO_CONTROL_IACK );
259 				m_irq_handler(0);
260 			}
261 			if( ( m_control & SIO_CONTROL_DTR ) != 0 )
262 			{
263 				m_dtr_handler(0);
264 			}
265 			else
266 			{
267 				m_dtr_handler(1);
268 			}
269 		}
270 		break;
271 	case 3:
272 		if( ACCESSING_BITS_0_15 )
273 		{
274 			verboselog( *this, 0, "psx_sio_w( %08x, %08x, %08x )\n", offset, data, mem_mask );
275 		}
276 		if( ACCESSING_BITS_16_31 )
277 		{
278 			m_baud = data >> 16;
279 			verboselog( *this, 1, "psx_sio_w %s baud %04x\n", tag(), data >> 16 );
280 		}
281 		break;
282 	default:
283 		verboselog( *this, 0, "psx_sio_w( %08x, %08x, %08x )\n", offset, data, mem_mask );
284 		break;
285 	}
286 }
287 
read(offs_t offset,uint32_t mem_mask)288 uint32_t psxsio_device::read(offs_t offset, uint32_t mem_mask)
289 {
290 	uint32_t data;
291 
292 	switch( offset % 4 )
293 	{
294 	case 0:
295 		data = m_rx_data;
296 		m_status &= ~( SIO_STATUS_RX_RDY );
297 		m_rx_data = 0xff;
298 		verboselog( *this, 1, "psx_sio_r %s data %02x (%08x)\n", tag(), data, mem_mask );
299 		break;
300 	case 1:
301 		data = m_status;
302 		if( ACCESSING_BITS_0_15 )
303 		{
304 			verboselog( *this, 1, "psx_sio_r %s status %04x\n", tag(), data & 0xffff );
305 		}
306 		if( ACCESSING_BITS_16_31 )
307 		{
308 			verboselog( *this, 0, "psx_sio_r( %08x, %08x ) %08x\n", offset, mem_mask, data );
309 		}
310 		break;
311 	case 2:
312 		data = ( m_control << 16 ) | m_mode;
313 		if( ACCESSING_BITS_0_15 )
314 		{
315 			verboselog( *this, 1, "psx_sio_r %s mode %04x\n", tag(), data & 0xffff );
316 		}
317 		if( ACCESSING_BITS_16_31 )
318 		{
319 			verboselog( *this, 1, "psx_sio_r %s control %04x\n", tag(), data >> 16 );
320 		}
321 		break;
322 	case 3:
323 		data = m_baud << 16;
324 		if( ACCESSING_BITS_0_15 )
325 		{
326 			verboselog( *this, 0, "psx_sio_r( %08x, %08x ) %08x\n", offset, mem_mask, data );
327 		}
328 		if( ACCESSING_BITS_16_31 )
329 		{
330 			verboselog( *this, 1, "psx_sio_r %s baud %04x\n", tag(), data >> 16 );
331 		}
332 		break;
333 	default:
334 		data = 0;
335 		verboselog( *this, 0, "psx_sio_r( %08x, %08x ) %08x\n", offset, mem_mask, data );
336 		break;
337 	}
338 	return data;
339 }
340 
WRITE_LINE_MEMBER(psxsio_device::write_rxd)341 WRITE_LINE_MEMBER(psxsio_device::write_rxd)
342 {
343 	m_rxd = state;
344 }
345 
WRITE_LINE_MEMBER(psxsio_device::write_dsr)346 WRITE_LINE_MEMBER(psxsio_device::write_dsr)
347 {
348 	if (state)
349 	{
350 		m_status &= ~SIO_STATUS_DSR;
351 	}
352 	else if ((m_status & SIO_STATUS_DSR) == 0)
353 	{
354 		m_status |= SIO_STATUS_DSR;
355 
356 		if( ( m_control & SIO_CONTROL_DSR_IENA ) != 0 )
357 		{
358 			sio_interrupt();
359 		}
360 	}
361 }
362