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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
|
// license:BSD-3-Clause
// copyright-holders:Enik Land
/**********************************************************************
Sega SK-1100 keyboard link cable emulation
The cable is used only to link two Mark III's through keyboard, what
is supported by the game F-16 Fighting Falcon for its 2 players mode.
Keyboard link cable info (originally from http://homepage3.nifty.com/st-2/,
but taken from http://www.smspower.org/Games/F16FightingFalcon-SMS-Talk):
- Cable is 7-pin DIN.
- Crossover scheme of the cable to connect pins
From To
1 1
2 6
3 3
4 5
5 4
6 2
7 7
Pinout of the printer port (from Charles MacDonald's sc3000h-20040729.txt
document, with the function of pin 6 corrected to /FAULT).
Numbering in counterclockwise/anticlockwise direction:
1 : Unused (not connected to anything)
2 : PPI PC5 (DATA output)
3 : PPI PC7 (/FEED output)
4 : PPI PB6 (BUSY input)
5 : PPI PC6 (/RESET output)
6 : PPI PB5 (/FAULT input)
7 : GND
**********************************************************************/
#include "emu.h"
#include "kblink.h"
//**************************************************************************
// DEVICE DEFINITIONS
//**************************************************************************
DEFINE_DEVICE_TYPE(SK1100_LINK_CABLE, sk1100_link_cable_device, "sk1100_link_cable", "SK-1100 Link Cable")
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
//-------------------------------------------------
// sk1100_link_cable_device - constructor
//-------------------------------------------------
sk1100_link_cable_device::sk1100_link_cable_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
device_t(mconfig, SK1100_LINK_CABLE, tag, owner, clock),
device_sk1100_printer_port_interface(mconfig, *this),
m_stream(*this, "stream"),
m_input_count(0),
m_input_index(0),
m_timer_poll(nullptr),
m_timer_send(nullptr),
m_timer_read(nullptr),
m_update_received_data(true),
m_data(0),
m_reset(0),
m_feed(0),
m_busy(0),
m_fault(0)
{
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void sk1100_link_cable_device::device_start()
{
m_timer_poll = timer_alloc(FUNC(sk1100_link_cable_device::update_queue), this);
m_timer_send = timer_alloc(FUNC(sk1100_link_cable_device::send_tick), this);
m_timer_read = timer_alloc(FUNC(sk1100_link_cable_device::read_tick), this);
/* register for state saving */
save_item(NAME(m_data));
save_item(NAME(m_reset));
save_item(NAME(m_feed));
save_item(NAME(m_busy));
save_item(NAME(m_fault));
save_item(NAME(m_update_received_data));
save_item(NAME(m_input_count));
save_item(NAME(m_input_index));
save_pointer(NAME(m_input_buffer), sizeof(m_input_buffer));
}
//-------------------------------------------------
// device_reset - device-specific reset
//-------------------------------------------------
void sk1100_link_cable_device::device_reset()
{
update_queue(0);
}
//-------------------------------------------------
// device_add_mconfig - add device configuration
//-------------------------------------------------
void sk1100_link_cable_device::device_add_mconfig(machine_config &config)
{
BITBANGER(config, m_stream, 0);
}
TIMER_CALLBACK_MEMBER(sk1100_link_cable_device::update_queue)
{
if (m_input_index == m_input_count)
{
m_input_index = 0;
m_input_count = m_stream->input(m_input_buffer, sizeof(m_input_buffer));
if (!m_input_count)
{
m_timer_poll->adjust(attotime::from_hz(XTAL(10'738'635)/3));
}
}
}
TIMER_CALLBACK_MEMBER(sk1100_link_cable_device::send_tick)
{
m_stream->output(u8(param));
}
TIMER_CALLBACK_MEMBER(sk1100_link_cable_device::read_tick)
{
m_update_received_data = true;
}
void sk1100_link_cable_device::set_data_read()
{
// Check if a new byte from the input buffer was read for this timeslice.
if (m_update_received_data == true)
{
if (m_input_count != 0)
{
u8 byte = m_input_buffer[m_input_index++];
// there is no way to read what was sent from peer as feed bit.
m_fault = BIT(byte, 0); // sent from peer as data bit
m_busy = BIT(byte, 1); // sent from peer as reset bit
update_queue(0);
}
// Set to read next byte only after the end of this timeslice.
m_update_received_data = false;
m_timer_read->adjust(attotime::zero);
}
}
void sk1100_link_cable_device::set_data_transfer()
{
u8 byte = (m_feed << 2) | (m_reset << 1) | m_data;
m_timer_send->adjust(attotime::zero, byte);
}
|