1 // license:GPL-2.0+
2 // copyright-holders:Raphael Nabet
3 /*
4     733 ASR emulation
5 
6     We are emulating a TI Model 733 ASR ("Silent 700") data terminal,
7     interfaced through a TI asynchronous EIA/TTY interface module.
8 
9     The ASR features a printer, a keyboard and a tape unit (which is not
10     emulated).  The ASR is attached to the computer with a serial interface.
11 
12     References:
13     945401-9701 Model 990/4 Computer System Field Maintenance Manual p. C-1,
14     945250-9701 990 Computer Family Systems Handbook pp. 5-9 through 5-16,
15     0943442-9701 Model 990 Computer Reference Manual Preliminary pp. 3-13
16     through 3-21 and 3-39 through 3-44.
17 
18     TODO:
19     * separate ASR emulation from EIA interface emulation?
20     * implement tape interface?
21 
22     Raphael Nabet 2003
23 
24     Rewritten as class
25     Michael Zapf, 2014
26 */
27 
28 #include "emu.h"
29 #include "733_asr.h"
30 
31 #include <algorithm>
32 
33 enum
34 {
35 	/*ASROutQueueSize = 32,*/
36 
37 	asr_window_offset_x = 0,
38 	asr_window_offset_y = 0,
39 	asr_window_width = 640,
40 	asr_window_height = 480,
41 	asr_scroll_step = 8
42 };
43 
44 enum
45 {
46 	AS_wrq_mask = 1 << 3,
47 	AS_rrq_mask = 1 << 4,
48 	AS_dsr_mask = 1 << 6,
49 	AS_int_mask = 1 << 7,
50 
51 	AM_dtr_mask = 1 << 1,
52 	AM_rts_mask = 1 << 2,
53 	AM_enint_mask = 1 << 6
54 };
55 
56 enum
57 {
58 	asrfontdata_size = 96/*128*/*8
59 };
60 
61 static const gfx_layout fontlayout =
62 {
63 	6, 8,           /* 6*8 characters */
64 	/*96*/128,              /* 96 characters */
65 	1,              /* 1 bit per pixel */
66 	{ 0 },
67 	{ 0, 1, 2, 3, 4, 5, 6, 7 }, /* straightforward layout */
68 	{ 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8 },
69 	8*8 /* every char takes 8 consecutive bytes */
70 };
71 
72 static GFXDECODE_START( gfx_asr733 )
73 	GFXDECODE_ENTRY( asr733_chr_region, 0, fontlayout, 0, 1 )
74 GFXDECODE_END
75 
76 
77 DEFINE_DEVICE_TYPE(ASR733, asr733_device, "asr733", "733 ASR")
78 
asr733_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)79 asr733_device::asr733_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
80 	: device_t(mconfig, ASR733, tag, owner, clock)
81 	, device_gfx_interface(mconfig, *this, gfx_asr733, "palette")
82 	, m_screen(*this, "screen")
83 	, m_keyint_line(*this)
84 	, m_lineint_line(*this)
85 {
86 }
87 
88 //-------------------------------------------------
89 //  device_start - device-specific startup
90 //-------------------------------------------------
91 
device_start()92 void asr733_device::device_start()
93 {
94 	int width = m_screen->width();
95 	int height = m_screen->height();
96 	const rectangle &visarea = m_screen->visible_area();
97 
98 	m_last_key_pressed = 0x80;
99 	m_bitmap = std::make_unique<bitmap_ind16>(width, height);
100 
101 	m_bitmap->fill(0, visarea);
102 
103 	m_keyint_line.resolve();
104 	m_lineint_line.resolve();
105 
106 	m_line_timer = timer_alloc(0);
107 
108 	uint8_t *dst;
109 
110 	static const unsigned char fontdata6x8[asrfontdata_size] =
111 	{   /* ASCII characters */
112 		0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x20,0x20,0x20,0x00,0x20,0x00,
113 		0x50,0x50,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x50,0xf8,0x50,0xf8,0x50,0x00,0x00,
114 		0x20,0x70,0xc0,0x70,0x18,0xf0,0x20,0x00,0x40,0xa4,0x48,0x10,0x20,0x48,0x94,0x08,
115 		0x60,0x90,0xa0,0x40,0xa8,0x90,0x68,0x00,0x10,0x20,0x40,0x00,0x00,0x00,0x00,0x00,
116 		0x20,0x40,0x40,0x40,0x40,0x40,0x20,0x00,0x10,0x08,0x08,0x08,0x08,0x08,0x10,0x00,
117 		0x20,0xa8,0x70,0xf8,0x70,0xa8,0x20,0x00,0x00,0x20,0x20,0xf8,0x20,0x20,0x00,0x00,
118 		0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x60,0x00,0x00,0x00,0xf8,0x00,0x00,0x00,0x00,
119 		0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x08,0x10,0x20,0x40,0x80,0x00,0x00,
120 		0x70,0x88,0x88,0x88,0x88,0x88,0x70,0x00,0x10,0x30,0x10,0x10,0x10,0x10,0x10,0x00,
121 		0x70,0x88,0x08,0x10,0x20,0x40,0xf8,0x00,0x70,0x88,0x08,0x30,0x08,0x88,0x70,0x00,
122 		0x10,0x30,0x50,0x90,0xf8,0x10,0x10,0x00,0xf8,0x80,0xf0,0x08,0x08,0x88,0x70,0x00,
123 		0x70,0x80,0xf0,0x88,0x88,0x88,0x70,0x00,0xf8,0x08,0x08,0x10,0x20,0x20,0x20,0x00,
124 		0x70,0x88,0x88,0x70,0x88,0x88,0x70,0x00,0x70,0x88,0x88,0x88,0x78,0x08,0x70,0x00,
125 		0x00,0x00,0x30,0x30,0x00,0x30,0x30,0x00,0x00,0x00,0x30,0x30,0x00,0x30,0x30,0x60,
126 		0x10,0x20,0x40,0x80,0x40,0x20,0x10,0x00,0x00,0x00,0xf8,0x00,0xf8,0x00,0x00,0x00,
127 		0x40,0x20,0x10,0x08,0x10,0x20,0x40,0x00,0x70,0x88,0x08,0x10,0x20,0x00,0x20,0x00,
128 		0x70,0x88,0xb8,0xa8,0xb8,0x80,0x70,0x00,0x70,0x88,0x88,0xf8,0x88,0x88,0x88,0x00,
129 		0xf0,0x88,0x88,0xf0,0x88,0x88,0xf0,0x00,0x70,0x88,0x80,0x80,0x80,0x88,0x70,0x00,
130 		0xf0,0x88,0x88,0x88,0x88,0x88,0xf0,0x00,0xf8,0x80,0x80,0xf0,0x80,0x80,0xf8,0x00,
131 		0xf8,0x80,0x80,0xf0,0x80,0x80,0x80,0x00,0x70,0x88,0x80,0x98,0x88,0x88,0x70,0x00,
132 		0x88,0x88,0x88,0xf8,0x88,0x88,0x88,0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x00,
133 		0x08,0x08,0x08,0x08,0x88,0x88,0x70,0x00,0x88,0x90,0xa0,0xc0,0xa0,0x90,0x88,0x00,
134 		0x80,0x80,0x80,0x80,0x80,0x80,0xf8,0x00,0x88,0xd8,0xa8,0x88,0x88,0x88,0x88,0x00,
135 		0x88,0xc8,0xa8,0x98,0x88,0x88,0x88,0x00,0x70,0x88,0x88,0x88,0x88,0x88,0x70,0x00,
136 		0xf0,0x88,0x88,0xf0,0x80,0x80,0x80,0x00,0x70,0x88,0x88,0x88,0x88,0x88,0x70,0x08,
137 		0xf0,0x88,0x88,0xf0,0x88,0x88,0x88,0x00,0x70,0x88,0x80,0x70,0x08,0x88,0x70,0x00,
138 		0xf8,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x88,0x88,0x88,0x88,0x88,0x88,0x70,0x00,
139 		0x88,0x88,0x88,0x88,0x88,0x50,0x20,0x00,0x88,0x88,0x88,0x88,0xa8,0xd8,0x88,0x00,
140 		0x88,0x50,0x20,0x20,0x20,0x50,0x88,0x00,0x88,0x88,0x88,0x50,0x20,0x20,0x20,0x00,
141 		0xf8,0x08,0x10,0x20,0x40,0x80,0xf8,0x00,0x30,0x20,0x20,0x20,0x20,0x20,0x30,0x00,
142 		0x40,0x40,0x20,0x20,0x10,0x10,0x08,0x08,0x30,0x10,0x10,0x10,0x10,0x10,0x30,0x00,
143 		0x20,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,
144 		0x40,0x20,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x08,0x78,0x88,0x78,0x00,
145 		0x80,0x80,0xf0,0x88,0x88,0x88,0xf0,0x00,0x00,0x00,0x70,0x88,0x80,0x80,0x78,0x00,
146 		0x08,0x08,0x78,0x88,0x88,0x88,0x78,0x00,0x00,0x00,0x70,0x88,0xf8,0x80,0x78,0x00,
147 		0x18,0x20,0x70,0x20,0x20,0x20,0x20,0x00,0x00,0x00,0x78,0x88,0x88,0x78,0x08,0x70,
148 		0x80,0x80,0xf0,0x88,0x88,0x88,0x88,0x00,0x20,0x00,0x20,0x20,0x20,0x20,0x20,0x00,
149 		0x20,0x00,0x20,0x20,0x20,0x20,0x20,0xc0,0x80,0x80,0x90,0xa0,0xe0,0x90,0x88,0x00,
150 		0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x00,0x00,0xf0,0xa8,0xa8,0xa8,0xa8,0x00,
151 		0x00,0x00,0xb0,0xc8,0x88,0x88,0x88,0x00,0x00,0x00,0x70,0x88,0x88,0x88,0x70,0x00,
152 		0x00,0x00,0xf0,0x88,0x88,0xf0,0x80,0x80,0x00,0x00,0x78,0x88,0x88,0x78,0x08,0x08,
153 		0x00,0x00,0xb0,0xc8,0x80,0x80,0x80,0x00,0x00,0x00,0x78,0x80,0x70,0x08,0xf0,0x00,
154 		0x20,0x20,0x70,0x20,0x20,0x20,0x18,0x00,0x00,0x00,0x88,0x88,0x88,0x98,0x68,0x00,
155 		0x00,0x00,0x88,0x88,0x88,0x50,0x20,0x00,0x00,0x00,0xa8,0xa8,0xa8,0xa8,0x50,0x00,
156 		0x00,0x00,0x88,0x50,0x20,0x50,0x88,0x00,0x00,0x00,0x88,0x88,0x88,0x78,0x08,0x70,
157 		0x00,0x00,0xf8,0x10,0x20,0x40,0xf8,0x00,0x08,0x10,0x10,0x20,0x10,0x10,0x08,0x00,
158 		0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x40,0x20,0x20,0x10,0x20,0x20,0x40,0x00,
159 		0x00,0x68,0xb0,0x00,0x00,0x00,0x00,0x00,0x20,0x50,0x20,0x50,0xa8,0x50,0x00,0x00
160 	};
161 
162 	dst = machine().root_device().memregion(asr733_chr_region)->base();
163 
164 	memcpy(dst, fontdata6x8, asrfontdata_size);
165 }
166 
167 //-------------------------------------------------
168 //  device_reset - device-specific reset
169 //-------------------------------------------------
170 
device_reset()171 void asr733_device::device_reset()
172 {
173 	/*m_OutQueueLen = 0;*/
174 
175 	m_status = AS_dsr_mask | AS_wrq_mask;
176 	m_mode = 0;
177 	m_line_timer->adjust(attotime::from_msec(0), 0, attotime::from_hz(60));
178 
179 	set_interrupt_line();
180 }
181 
set_interrupt_line()182 void asr733_device::set_interrupt_line()
183 {
184 	if ((m_mode & AM_enint_mask) && (m_new_status_flag))  /* right??? */
185 	{
186 		m_status |= AS_int_mask;
187 		m_keyint_line(ASSERT_LINE);
188 	}
189 	else
190 	{
191 		m_status &= ~AS_int_mask;
192 		m_keyint_line(CLEAR_LINE);
193 	}
194 }
195 
196 /* write a single char on screen */
draw_char(int character,int x,int y,int color)197 void asr733_device::draw_char(int character, int x, int y, int color)
198 {
199 	gfx(0)->opaque(*m_bitmap, m_bitmap->cliprect(), character-32, color, 0, 0, x+1, y);
200 }
201 
linefeed()202 void asr733_device::linefeed()
203 {
204 	uint8_t buf[asr_window_width];
205 
206 	assert(asr_window_offset_x + asr_window_width <= m_bitmap->width());
207 	assert(asr_window_offset_y + asr_window_height <= m_bitmap->height());
208 	for (int y=asr_window_offset_y; y<asr_window_offset_y+asr_window_height-asr_scroll_step; y++)
209 	{
210 		std::copy_n(&m_bitmap->pix(y+asr_scroll_step, asr_window_offset_x), asr_window_width, buf);
211 		draw_scanline8(*m_bitmap, asr_window_offset_x, y, asr_window_width, buf, palette().pens());
212 	}
213 
214 	const rectangle asr_scroll_clear_window(
215 		asr_window_offset_x,                                    /* min_x */
216 		asr_window_offset_x+asr_window_width-1,                 /* max_x */
217 		asr_window_offset_y+asr_window_height-asr_scroll_step,  /* min_y */
218 		asr_window_offset_y+asr_window_height-1                 /* max_y */
219 	);
220 	m_bitmap->fill(0, asr_scroll_clear_window);
221 }
222 
transmit(uint8_t data)223 void asr733_device::transmit(uint8_t data)
224 {
225 	switch (data)
226 	{
227 	/* aux device control chars */
228 	case 0x05:
229 		/* ENQ -> "WRU": ??? */
230 		break;
231 
232 	case 0x11:
233 		/* DC1 -> "X-ON": transmit on??? */
234 		break;
235 
236 	case 0x12:
237 		/* DC2 -> "X-OFF": transmit off??? */
238 		break;
239 
240 	case 0x13:
241 		/* DC3 -> "TAPE": tape on??? */
242 		break;
243 
244 	case 0x14:
245 		/* DC4 -> "-T-A-P-E-" ("TAPE" with overstrike): tape off??? */
246 		break;
247 
248 
249 	/* printer control chars */
250 	case 0x07:
251 		/* BELL: 250ms beep */
252 		break;
253 
254 	case 0x08:
255 		/* BS: backspace */
256 		if (m_x > 0)
257 			m_x--;
258 		break;
259 
260 	case 0x0A:
261 		/* LF: line feed */
262 		linefeed();
263 		break;
264 
265 	case 0x0D:
266 		/* CR: carriage return */
267 		m_x = 0;
268 		break;
269 
270 
271 	default:
272 		if ((data < 0x20) || (data == 0x7f) || (data >= 0x80))
273 			/* ignore control characters */
274 			break;
275 
276 		if (m_x == 80)
277 		{
278 			m_x = 0;
279 			linefeed();
280 		}
281 		draw_char(data, asr_window_offset_x + m_x*8, asr_window_offset_y+asr_window_height-8, 0);
282 		m_x++;
283 		break;
284 	}
285 
286 	m_status |= AS_wrq_mask;
287 	m_new_status_flag = 1;   /* right??? */
288 	set_interrupt_line();
289 }
290 
291 #if 0
292 void asr733_device::receive_callback(int dummy)
293 {
294 	(void) dummy;
295 
296 	m_recv_buf = m_OutQueue[m_OutQueueHead];
297 	m_OutQueueHead = (m_OutQueueHead + 1) % ASROutQueueSize;
298 	m_OutQueueLen--;
299 
300 	m_status |= AS_rrq_mask;
301 	m_new_status_flag = 1;   /* right??? */
302 	set_interrupt_line();
303 }
304 #endif
305 
306 /*
307     0-7: receive buffer
308     8: XMITING transmit in progress, 1 if transmitting
309     9: TIMERR timing error, 1 if error
310     10: RCR reverse channel receive, not used
311         "ASR733/33 ID" 1 -> TTY (???) (2270509-9701 pp. G-9 & G-10)
312     11: WRQ write request, 1 if ready to transmit
313     12: RRQ read request, 1 if ready to receive
314     13: DCD data carrier detect, not used
315     14: DSR data set ready, 1 if online
316     15: INT interrupt, 1 if interrupt
317 */
cru_r(offs_t offset)318 uint8_t asr733_device::cru_r(offs_t offset)
319 {
320 	int reply = 0;
321 
322 	switch (offset >> 3)
323 	{
324 	case 0:
325 		/* receive buffer */
326 		reply = m_recv_buf;
327 		break;
328 
329 	case 1:
330 		/* status register */
331 		reply = m_status;
332 		break;
333 	}
334 
335 	return BIT(reply, offset & 7);
336 }
337 
338 /*
339     0-7: transmit buffer
340     8: not used
341     9: DTR data terminal ready (set to 1)
342     10: RTS request to send (set to 1)
343     11: CLRWRQ clear write request (write any value to execute)
344     12: CLRRRQ clear read request (write any value to execute)
345     13: CLRNSF clear new status flag - clear DSR/DCD interrupts (write any value to execute)
346     14: enable interrupts, 1 to enable interrupts
347     15: diagnostic mode, 0 for normal mode
348 */
cru_w(offs_t offset,uint8_t data)349 void asr733_device::cru_w(offs_t offset, uint8_t data)
350 {
351 	switch (offset)
352 	{
353 	case 0:
354 	case 1:
355 	case 2:
356 	case 3:
357 	case 4:
358 	case 5:
359 	case 6:
360 	case 7:
361 		/* transmit buffer */
362 		if (data)
363 			m_xmit_buf |= 1 << offset;
364 		else
365 			m_xmit_buf &= ~ (1 << offset);
366 		if ((offset == 7) && (m_mode & AM_dtr_mask) && (m_mode & AM_rts_mask))    /* right??? */
367 			transmit(m_xmit_buf);
368 		break;
369 
370 	case 8:     /* not used */
371 		break;
372 
373 	case 9:     /* data terminal ready (set to 1) */
374 	case 10:    /* request to send (set to 1) */
375 	case 14:    /* enable interrupts, 1 to enable interrupts */
376 	case 15:    /* diagnostic mode, 0 for normal mode */
377 		if (data)
378 			m_mode |= 1 << (offset - 8);
379 		else
380 			m_mode &= ~ (1 << (offset - 8));
381 		if (offset == 14)
382 			set_interrupt_line();
383 		break;
384 
385 	case 11:    /* clear write request (write any value to execute) */
386 	case 12:    /* clear read request (write any value to execute) */
387 		m_status &= ~ (1 << (offset - 8));
388 		set_interrupt_line();
389 		break;
390 
391 	case 13:    /* clear new status flag - whatever it means (write any value to execute) */
392 		m_new_status_flag = 0;
393 		set_interrupt_line();
394 		break;
395 	}
396 }
397 
398 /*
399     Video refresh
400 */
refresh(bitmap_ind16 & bitmap,int x,int y)401 void asr733_device::refresh(bitmap_ind16 &bitmap, int x, int y)
402 {
403 	copybitmap(bitmap, *m_bitmap, 0, 0, x, y, m_bitmap->cliprect());
404 }
405 
406 
407 /*
408     Time callbacks
409 */
device_timer(emu_timer & timer,device_timer_id id,int param,void * ptr)410 void asr733_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
411 {
412 	check_keyboard();
413 	m_lineint_line(ASSERT_LINE);
414 	m_lineint_line(CLEAR_LINE);
415 }
416 
417 static const unsigned char key_translate[3][51] =
418 {
419 	{   /* unshifted */
420 		'1',
421 		'2',
422 		'3',
423 		'4',
424 		'5',
425 		'6',
426 		'7',
427 		'8',
428 		'9',
429 		'0',
430 		':',
431 		'-',
432 
433 		0x1b,
434 		'Q',
435 		'W',
436 		'E',
437 		'R',
438 		'T',
439 		'Y',
440 		'U',
441 		'I',
442 		'O',
443 		'P',
444 		0x0a,
445 		0x0d,
446 
447 		0,
448 		'A',
449 		'S',
450 		'D',
451 		'F',
452 		'G',
453 		'H',
454 		'J',
455 		'K',
456 		'L',
457 		';',
458 		0x08,
459 		0,
460 
461 		0,
462 		'Z',
463 		'X',
464 		'C',
465 		'V',
466 		'B',
467 		'N',
468 		'M',
469 		',',
470 		'.',
471 		'/',
472 		0,
473 
474 		' '
475 	},
476 	{   /* shifted */
477 		'!',
478 		'"',
479 		'#',
480 		'$',
481 		'%',
482 		'&',
483 		'^',
484 		'(',
485 		')',
486 		' ',
487 		'*',
488 		'=',
489 
490 		0x1b,
491 		'Q',
492 		'W',
493 		'E',
494 		'R',
495 		'T',
496 		'Y',
497 		'U',
498 		'I',
499 		'_',
500 		'@',
501 		0x0a,
502 		0x0d,
503 
504 		0,
505 		'A',
506 		'S',
507 		'D',
508 		'F',
509 		'G',
510 		'H',
511 		'J',
512 		0,
513 		'/',
514 		'+',
515 		0x08,
516 		0,
517 
518 		0,
519 		'Z',
520 		'X',
521 		'C',
522 		'V',
523 		'B',
524 		'^',
525 		'|',
526 		'<',
527 		'>',
528 		'?',
529 		0,
530 
531 		' '
532 	},
533 	{   /* control */
534 		'1',
535 		'2',
536 		'3',
537 		'4',
538 		'5',
539 		'6',
540 		'7',
541 		'8',
542 		'9',
543 		'0',
544 		':',
545 		'-',
546 
547 		0x1b,
548 		0x11,
549 		0x17,
550 		0x05,
551 		0x12,
552 		0x14,
553 		0x19,
554 		0x15,
555 		0x09,
556 		0x0f,
557 		0x10,
558 		0x0a,
559 		0x0d,
560 
561 		0,
562 		0x01,
563 		0x13,
564 		0x04,
565 		0x06,
566 		0x07,
567 		0x08,
568 		0x0a,
569 		0x0b,
570 		0x0c,
571 		';',
572 		0x08,
573 		0,
574 
575 		0,
576 		0x1a,
577 		0x18,
578 		0x03,
579 		0x16,
580 		0x02,
581 		0x0e,
582 		0x0d,
583 		',',
584 		'.',
585 		'/',
586 		0,
587 
588 		' '
589 	}
590 };
591 
592 
593 /*
594     keyboard handler: should be called regularly by machine code, for instance
595     every Video Blank Interrupt.
596 */
check_keyboard()597 void asr733_device::check_keyboard()
598 {
599 	enum modifier_state_t
600 	{
601 		/* key modifier states */
602 		unshifted = 0, shift, control,
603 		/* special value to stop repeat if the modifier state changes */
604 		special_debounce = -1
605 	} ;
606 
607 	enum { repeat_delay = 5 /* approx. 1/10s */ };
608 
609 	//uint16_t key_buf[6];
610 	uint16_t key_buf[4];
611 	int i, j;
612 	modifier_state_t modifier_state;
613 	int repeat_mode;
614 
615 	static const char *const keynames[] = { "KEY0", "KEY1", "KEY2", "KEY3" };
616 
617 	/* read current key state */
618 	/* 2008-05 FP: in 733_asr.h there are only 4 input ports defined... */
619 	/* for (i = 0; i < 6; i++) */
620 	for (i = 0; i < 4; i++)
621 	{
622 		key_buf[i] = ioport(keynames[i])->read();
623 	}
624 
625 	/* process key modifiers */
626 	if (key_buf[1] & 0x0200)
627 		modifier_state = control;
628 	else if ((key_buf[2] & 0x0040) || (key_buf[3] & 0x0002))
629 		modifier_state = shift;
630 	else
631 		modifier_state = unshifted;
632 
633 	/* test repeat key */
634 	repeat_mode = key_buf[2] & 0x0020;
635 
636 	/* remove modifier keys */
637 	key_buf[1] &= ~0x0200;
638 	key_buf[2] &= ~0x0060;
639 	key_buf[3] &= ~0x0002;
640 
641 	if (! repeat_mode)
642 		/* reset REPEAT timer if the REPEAT key is not pressed */
643 		m_repeat_timer = 0;
644 
645 	if ( !(m_last_key_pressed & 0x80) && (key_buf[m_last_key_pressed >> 4] & (1 << (m_last_key_pressed & 0xf))))
646 	{
647 		/* last key has not been released */
648 		if (modifier_state == m_last_modifier_state)
649 		{
650 			/* handle REPEAT mode if applicable */
651 			if ((repeat_mode) && (++m_repeat_timer == repeat_delay))
652 			{
653 				if (m_status & AS_rrq_mask)
654 				{   /* keyboard buffer full */
655 					m_repeat_timer--;
656 				}
657 				else
658 				{   /* repeat current key */
659 					m_status |= AS_rrq_mask;
660 					m_new_status_flag = 1;   /* right??? */
661 					set_interrupt_line();
662 					m_repeat_timer = 0;
663 				}
664 			}
665 		}
666 		else
667 		{
668 			m_repeat_timer = 0;
669 			m_last_modifier_state = special_debounce;
670 		}
671 	}
672 	else
673 	{
674 		m_last_key_pressed = 0x80;
675 
676 		if (m_status & AS_rrq_mask)
677 		{   /* keyboard buffer full */
678 			/* do nothing */
679 		}
680 		else
681 		{
682 			//for (i=0; i<6; i++)
683 			for (i=0; i<4; i++)
684 			{
685 				for (j=0; j<16; j++)
686 				{
687 					if (key_buf[i] & (1 << j))
688 					{
689 						m_last_key_pressed = (i << 4) | j;
690 						m_last_modifier_state = modifier_state;
691 
692 						m_recv_buf = (int)key_translate[modifier_state][m_last_key_pressed];
693 						m_status |= AS_rrq_mask;
694 						m_new_status_flag = 1;   /* right??? */
695 						set_interrupt_line();
696 						return;
697 					}
698 				}
699 			}
700 		}
701 	}
702 }
703 
screen_update(screen_device & screen,bitmap_ind16 & bitmap,const rectangle & cliprect)704 uint32_t asr733_device::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
705 {
706 	refresh(bitmap, 0, 0);
707 	return 0;
708 }
709 
710 
711 INPUT_PORTS_START( asr733 )
712 	PORT_START("KEY0")  /* keys 1-16 */                                                                 \
PORT_CODE(KEYCODE_1)713 		PORT_BIT(0x0001, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("1") PORT_CODE(KEYCODE_1)      \
714 		PORT_BIT(0x0002, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("2") PORT_CODE(KEYCODE_2)      \
715 		PORT_BIT(0x0004, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("3") PORT_CODE(KEYCODE_3)      \
716 		PORT_BIT(0x0008, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("4") PORT_CODE(KEYCODE_4)      \
717 		PORT_BIT(0x0010, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("5") PORT_CODE(KEYCODE_5)      \
718 		PORT_BIT(0x0020, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("6") PORT_CODE(KEYCODE_6)      \
719 		PORT_BIT(0x0040, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("7") PORT_CODE(KEYCODE_7)      \
720 		PORT_BIT(0x0080, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("8") PORT_CODE(KEYCODE_8)      \
721 		PORT_BIT(0x0100, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("9") PORT_CODE(KEYCODE_9)      \
722 		PORT_BIT(0x0200, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("0") PORT_CODE(KEYCODE_0)      \
723 		PORT_BIT(0x0400, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME(":") PORT_CODE(KEYCODE_MINUS)  \
724 		PORT_BIT(0x0800, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("-") PORT_CODE(KEYCODE_EQUALS) \
725 		PORT_BIT(0x1000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("ESC") PORT_CODE(KEYCODE_ESC)      \
726 		PORT_BIT(0x2000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Q") PORT_CODE(KEYCODE_Q)      \
727 		PORT_BIT(0x4000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("W") PORT_CODE(KEYCODE_W)      \
728 		PORT_BIT(0x8000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("E") PORT_CODE(KEYCODE_E)      \
729 																								\
730 	PORT_START("KEY1")  /* keys 17-32 */                                                                \
731 		PORT_BIT(0x0001, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("R") PORT_CODE(KEYCODE_R)      \
732 		PORT_BIT(0x0002, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("T") PORT_CODE(KEYCODE_T)      \
733 		PORT_BIT(0x0004, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Y") PORT_CODE(KEYCODE_Y)      \
734 		PORT_BIT(0x0008, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("U") PORT_CODE(KEYCODE_U)      \
735 		PORT_BIT(0x0010, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("I") PORT_CODE(KEYCODE_I)      \
736 		PORT_BIT(0x0020, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("O") PORT_CODE(KEYCODE_O)      \
737 		PORT_BIT(0x0040, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("P") PORT_CODE(KEYCODE_P)      \
738 		PORT_BIT(0x0080, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("LINE FEED") PORT_CODE(KEYCODE_CLOSEBRACE) \
739 		PORT_BIT(0x0100, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("RETURN") PORT_CODE(KEYCODE_ENTER) \
740 		PORT_BIT(0x0200, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("CTRL") PORT_CODE(KEYCODE_LCONTROL)    \
741 		PORT_BIT(0x0400, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("A") PORT_CODE(KEYCODE_A)      \
742 		PORT_BIT(0x0800, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("S") PORT_CODE(KEYCODE_S)      \
743 		PORT_BIT(0x1000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("D") PORT_CODE(KEYCODE_D)      \
744 		PORT_BIT(0x2000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("F") PORT_CODE(KEYCODE_F)      \
745 		PORT_BIT(0x4000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("G") PORT_CODE(KEYCODE_G)      \
746 		PORT_BIT(0x8000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("H") PORT_CODE(KEYCODE_H)      \
747 																								\
748 	PORT_START("KEY2")  /* keys 33-48 */                                                                \
749 		PORT_BIT(0x0001, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("J") PORT_CODE(KEYCODE_J)      \
750 		PORT_BIT(0x0002, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("K") PORT_CODE(KEYCODE_K)      \
751 		PORT_BIT(0x0004, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("L") PORT_CODE(KEYCODE_L)      \
752 		PORT_BIT(0x0008, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME(";") PORT_CODE(KEYCODE_COLON)  \
753 		PORT_BIT(0x0010, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("RUB OUT") PORT_CODE(KEYCODE_BACKSPACE)    \
754 		PORT_BIT(0x0020, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("REPEAT") PORT_CODE(KEYCODE_RALT)  \
755 		/* hack for my mac that does not disciminate the right ALT key */                       \
756 		/* PORT_BIT(0x0020, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("REPEAT") PORT_CODE(KEYCODE_LALT) */    \
757 		PORT_BIT(0x0040, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("SHIFT") PORT_CODE(KEYCODE_LSHIFT) \
758 		PORT_BIT(0x0080, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Z") PORT_CODE(KEYCODE_Z)      \
759 		PORT_BIT(0x0100, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("X") PORT_CODE(KEYCODE_X)      \
760 		PORT_BIT(0x0200, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("C") PORT_CODE(KEYCODE_C)      \
761 		PORT_BIT(0x0400, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("V") PORT_CODE(KEYCODE_V)      \
762 		PORT_BIT(0x0800, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("B") PORT_CODE(KEYCODE_B)      \
763 		PORT_BIT(0x1000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("N") PORT_CODE(KEYCODE_N)      \
764 		PORT_BIT(0x2000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("M") PORT_CODE(KEYCODE_M)      \
765 		PORT_BIT(0x4000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME(",") PORT_CODE(KEYCODE_COMMA)  \
766 		PORT_BIT(0x8000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME(".") PORT_CODE(KEYCODE_STOP)   \
767 																								\
768 	PORT_START("KEY3")  /* keys 49-51 */                                                                \
769 		PORT_BIT(0x0001, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("/") PORT_CODE(KEYCODE_SLASH)  \
770 		PORT_BIT(0x0002, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("SHIFT") PORT_CODE(KEYCODE_RSHIFT) \
771 		PORT_BIT(0x0004, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("(SPACE)") PORT_CODE(KEYCODE_SPACE)
772 INPUT_PORTS_END
773 
774 ioport_constructor asr733_device::device_input_ports() const
775 {
776 	return INPUT_PORTS_NAME( asr733 );
777 }
778 
779 //-------------------------------------------------
780 //  device_add_mconfig - add device configuration
781 //-------------------------------------------------
782 
783 
device_add_mconfig(machine_config & config)784 void asr733_device::device_add_mconfig(machine_config &config)
785 {
786 	PALETTE(config, "palette", palette_device::MONOCHROME_INVERTED);
787 
788 	SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
789 	m_screen->set_refresh_hz(60);
790 	m_screen->set_vblank_time(ATTOSECONDS_IN_USEC(2500)); /* not accurate */
791 	m_screen->set_screen_update(FUNC(asr733_device::screen_update));
792 	m_screen->set_size(640, 480);
793 	m_screen->set_visarea(0, 640-1, 0, 480-1);
794 	m_screen->set_palette("palette");
795 }
796