1 // license:LGPL-2.1+
2 // copyright-holders:Angelo Salese
3 /***************************************************************************
4 
5 Acorn Archimedes KART interface
6 
7 TODO:
8 - FIFO
9 
10 ***************************************************************************/
11 
12 #include "emu.h"
13 #include "machine/aakart.h"
14 
15 
16 
17 //**************************************************************************
18 //  GLOBAL VARIABLES
19 //**************************************************************************
20 
21 // device type definition
22 DEFINE_DEVICE_TYPE(AAKART, aakart_device, "aakart", "Acorn Archimedes KART")
23 
24 #define HRST 0xff
25 #define RAK1 0xfe
26 #define RAK2 0xfd
27 #define BACK 0x3f
28 #define SMAK 0x33   /* keyboard + mouse ack */
29 #define MACK 0x32   /* mouse ack */
30 #define SACK 0x31   /* keyboard ack */
31 #define NACK 0x30   /* no data ack */
32 #define RQID 0x20
33 
34 //**************************************************************************
35 //  LIVE DEVICE
36 //**************************************************************************
37 
38 //-------------------------------------------------
39 //  aakart_device - constructor
40 //-------------------------------------------------
41 
aakart_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)42 aakart_device::aakart_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
43 	: device_t(mconfig, AAKART, tag, owner, clock), m_rxtimer(nullptr),
44 		m_txtimer(nullptr), m_mousetimer(nullptr), m_keybtimer(nullptr),
45 		m_out_tx_cb(*this),
46 		m_out_rx_cb(*this),
47 		m_tx_latch(0), m_rx(0), m_new_command(0), m_status(0), m_mouse_enable(0), m_keyb_enable(0)
48 {
49 }
50 
51 
52 //-------------------------------------------------
53 //  device_validity_check - perform validity checks
54 //  on this device
55 //-------------------------------------------------
56 
device_validity_check(validity_checker & valid) const57 void aakart_device::device_validity_check(validity_checker &valid) const
58 {
59 }
60 
61 
62 //-------------------------------------------------
63 //  device_start - device-specific startup
64 //-------------------------------------------------
65 
device_start()66 void aakart_device::device_start()
67 {
68 	m_out_tx_cb.resolve_safe();
69 	m_out_rx_cb.resolve_safe();
70 	m_rxtimer = timer_alloc(RX_TIMER);
71 	m_rxtimer->adjust(attotime::from_hz(clock()), 0, attotime::from_hz(clock()));
72 	m_txtimer = timer_alloc(TX_TIMER);
73 	m_txtimer->adjust(attotime::from_hz(1), 0, attotime::from_hz(clock()));
74 	m_mousetimer = timer_alloc(MOUSE_TIMER);
75 	m_mousetimer->adjust(attotime::from_hz(clock()), 0, attotime::from_hz(clock()));
76 	m_keybtimer = timer_alloc(KEYB_TIMER);
77 	m_keybtimer->adjust(attotime::from_hz(clock()), 0, attotime::from_hz(clock()));
78 }
79 
80 //-------------------------------------------------
81 //  device_reset - device-specific reset
82 //-------------------------------------------------
83 
device_reset()84 void aakart_device::device_reset()
85 {
86 	m_status = STATUS_HRST;
87 	m_new_command = 0;
88 	m_rx = -1;
89 	m_keyb_enable = 0;
90 	m_mouse_enable = 0;
91 	m_queue_size = 0;
92 }
93 
94 //-------------------------------------------------
95 //  device_timer - handler timer events
96 //-------------------------------------------------
97 
device_timer(emu_timer & timer,device_timer_id id,int param,void * ptr)98 void aakart_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
99 {
100 	if(id == TX_TIMER && m_new_command)
101 	{
102 		switch(m_tx_latch)
103 		{
104 			case 0x00:
105 			case 0x01:
106 			case 0x02:
107 			case 0x03:
108 			case 0x04:
109 			case 0x05:
110 			case 0x06:
111 			case 0x07:
112 				// ---- -x-- scroll lock
113 				// ---- --x- num lock
114 				// ---- ---x caps lock
115 				break;
116 			case 0x20:
117 				m_rx = 0x81;
118 				m_out_tx_cb(ASSERT_LINE);
119 				break;
120 			case 0x30:
121 			case 0x31:
122 			case 0x32:
123 			case 0x33:
124 				m_keyb_enable = m_tx_latch & 1;
125 				m_mouse_enable = (m_tx_latch & 2) >> 1;
126 				if(m_queue_size)
127 				{
128 					m_rx = m_queue[0] & 0xff;
129 					m_out_tx_cb(ASSERT_LINE);
130 				}
131 				break;
132 			case 0x3f:
133 				if(m_queue_size)
134 				{
135 					m_rx = (m_queue[0] >> 8) & 0xff;
136 					m_out_tx_cb(ASSERT_LINE);
137 
138 					m_queue_size--;
139 					for(int i=0; i<m_queue_size; i++)
140 						m_queue[i] = m_queue[i + 1];
141 				}
142 				break;
143 			case 0xfd:
144 				m_rx = 0xfd;
145 				m_out_tx_cb(ASSERT_LINE);
146 				break;
147 			case 0xfe:
148 				m_rx = 0xfe;
149 				m_out_tx_cb(ASSERT_LINE);
150 				break;
151 			case 0xff:
152 				m_rx = 0xff;
153 				m_out_tx_cb(ASSERT_LINE);
154 				break;
155 			default:
156 				//printf("%02x %02x %02x\n",m_tx_latch,m_rx_latch,m_keyb_enable);
157 				break;
158 		}
159 
160 		m_new_command = 0;
161 		m_out_rx_cb(ASSERT_LINE);
162 	}
163 	else if(id == TX_TIMER && m_queue_size && (m_keyb_enable || m_mouse_enable))
164 	{
165 		m_rx = m_queue[0] & 0xff;
166 		m_out_tx_cb(ASSERT_LINE);
167 	}
168 }
169 
170 //**************************************************************************
171 //  READ/WRITE HANDLERS
172 //**************************************************************************
173 
174 
read()175 uint8_t aakart_device::read()
176 {
177 	m_out_tx_cb(CLEAR_LINE);
178 	//machine().debug_break();
179 	return m_rx;
180 }
181 
write(uint8_t data)182 void aakart_device::write(uint8_t data)
183 {
184 	// if(m_new_command) printf("skip cmd %02x\n",data);
185 
186 	m_tx_latch = data;
187 	m_out_rx_cb(CLEAR_LINE);
188 	m_new_command |= 1;
189 }
190 
send_keycode_down(uint8_t row,uint8_t col)191 void aakart_device::send_keycode_down(uint8_t row, uint8_t col)
192 {
193 	//printf("keycode down\n");
194 	if (m_keyb_enable && m_queue_size < 0x10)
195 		m_queue[m_queue_size++] = ((col | 0xc0) << 8) | (row | 0xc0);
196 }
197 
send_keycode_up(uint8_t row,uint8_t col)198 void aakart_device::send_keycode_up(uint8_t row, uint8_t col)
199 {
200 	//printf("keycode up\n");
201 	if (m_keyb_enable && m_queue_size < 0x10)
202 		m_queue[m_queue_size++] = ((col | 0xd0) << 8) | (row | 0xd0);
203 }
204 
send_mouse(uint8_t x,uint8_t y)205 void aakart_device::send_mouse(uint8_t x, uint8_t y)
206 {
207 	if (m_mouse_enable && m_queue_size < 0x10)
208 		m_queue[m_queue_size++] = ((y & 0x7f) << 8) | (x & 0x7f);
209 }
210