mirror of
https://github.com/holub/mame
synced 2025-07-03 09:06:08 +03:00
vt100_kbd: Rewrite as UART-based serial device
This commit is contained in:
parent
e6e3804ce8
commit
b4a7ef663d
@ -533,7 +533,7 @@ MACHINES["ROC10937"] = true
|
||||
MACHINES["RP5C01"] = true
|
||||
MACHINES["RP5C15"] = true
|
||||
MACHINES["RP5H01"] = true
|
||||
--MACHINES["RSTBUF"] = true
|
||||
MACHINES["RSTBUF"] = true
|
||||
MACHINES["RTC4543"] = true
|
||||
MACHINES["RTC65271"] = true
|
||||
MACHINES["RTC9701"] = true
|
||||
|
@ -23,9 +23,11 @@
|
||||
#include "bus/rs232/rs232.h"
|
||||
#include "cpu/i8085/i8085.h"
|
||||
#include "cpu/z80/z80.h"
|
||||
#include "machine/ay31015.h"
|
||||
#include "machine/com8116.h"
|
||||
#include "machine/er1400.h"
|
||||
#include "machine/i8251.h"
|
||||
#include "machine/rstbuf.h"
|
||||
#include "machine/vt100_kbd.h"
|
||||
#include "video/vtvideo.h"
|
||||
#include "screen.h"
|
||||
@ -43,8 +45,10 @@ public:
|
||||
m_maincpu(*this, "maincpu"),
|
||||
m_crtc(*this, "vt100_video"),
|
||||
m_keyboard(*this, "keyboard"),
|
||||
m_kbduart(*this, "kbduart"),
|
||||
m_dbrg(*this, "dbrg"),
|
||||
m_nvr(*this, "nvr"),
|
||||
m_rstbuf(*this, "rstbuf"),
|
||||
m_p_ram(*this, "p_ram")
|
||||
{
|
||||
}
|
||||
@ -52,24 +56,20 @@ public:
|
||||
required_device<cpu_device> m_maincpu;
|
||||
required_device<vt100_video_device> m_crtc;
|
||||
required_device<vt100_keyboard_device> m_keyboard;
|
||||
required_device<ay31015_device> m_kbduart;
|
||||
required_device<com8116_device> m_dbrg;
|
||||
required_device<er1400_device> m_nvr;
|
||||
required_device<rst_pos_buffer_device> m_rstbuf;
|
||||
DECLARE_READ8_MEMBER(vt100_flags_r);
|
||||
DECLARE_WRITE_LINE_MEMBER(keyboard_int_w);
|
||||
DECLARE_WRITE8_MEMBER(vt100_keyboard_w);
|
||||
DECLARE_READ8_MEMBER(vt100_keyboard_r);
|
||||
DECLARE_WRITE8_MEMBER(vt100_baud_rate_w);
|
||||
DECLARE_WRITE8_MEMBER(vt100_nvr_latch_w);
|
||||
DECLARE_READ8_MEMBER(vt100_read_video_ram_r);
|
||||
DECLARE_WRITE_LINE_MEMBER(vert_freq_intr_w);
|
||||
DECLARE_WRITE8_MEMBER(uart_clock_w);
|
||||
required_shared_ptr<uint8_t> m_p_ram;
|
||||
bool m_keyboard_int;
|
||||
bool m_receiver_int;
|
||||
bool m_vertical_int;
|
||||
virtual void machine_start() override;
|
||||
virtual void machine_reset() override;
|
||||
uint32_t screen_update_vt100(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
|
||||
IRQ_CALLBACK_MEMBER(vt100_irq_callback);
|
||||
IRQ_CALLBACK_MEMBER(vt102_irq_callback);
|
||||
void vt102(machine_config &config);
|
||||
void vt100(machine_config &config);
|
||||
void vt180(machine_config &config);
|
||||
@ -119,27 +119,10 @@ READ8_MEMBER( vt100_state::vt100_flags_r )
|
||||
|
||||
ret |= !m_nvr->data_r() << 5;
|
||||
ret |= m_crtc->lba7_r() << 6;
|
||||
ret |= m_keyboard_int << 7;
|
||||
ret |= m_kbduart->tbmt_r() << 7;
|
||||
return ret;
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER(vt100_state::keyboard_int_w)
|
||||
{
|
||||
m_keyboard_int = state;
|
||||
if (state)
|
||||
m_maincpu->set_input_line(0, HOLD_LINE);
|
||||
}
|
||||
|
||||
WRITE8_MEMBER( vt100_state::vt100_keyboard_w )
|
||||
{
|
||||
m_keyboard->control_w(data);
|
||||
}
|
||||
|
||||
READ8_MEMBER( vt100_state::vt100_keyboard_r )
|
||||
{
|
||||
return m_keyboard->key_code_r();
|
||||
}
|
||||
|
||||
WRITE8_MEMBER( vt100_state::vt100_baud_rate_w )
|
||||
{
|
||||
m_dbrg->str_w(data & 0x0f);
|
||||
@ -173,10 +156,8 @@ ADDRESS_MAP_START(vt100_state::vt100_io)
|
||||
AM_RANGE (0x42, 0x42) AM_DEVWRITE("vt100_video", vt100_video_device, brightness_w)
|
||||
// 0x62 NVR latch
|
||||
AM_RANGE (0x62, 0x62) AM_WRITE(vt100_nvr_latch_w)
|
||||
// 0x82 Keyboard UART data output
|
||||
AM_RANGE (0x82, 0x82) AM_READ(vt100_keyboard_r)
|
||||
// 0x82 Keyboard UART data input
|
||||
AM_RANGE (0x82, 0x82) AM_WRITE(vt100_keyboard_w)
|
||||
// 0x82 Keyboard UART data
|
||||
AM_RANGE (0x82, 0x82) AM_DEVREADWRITE("kbduart", ay31015_device, receive, transmit)
|
||||
// 0xA2 Video processor DC012
|
||||
AM_RANGE (0xa2, 0xa2) AM_DEVWRITE("vt100_video", vt100_video_device, dc012_w)
|
||||
// 0xC2 Video processor DC011
|
||||
@ -201,30 +182,27 @@ uint32_t vt100_state::screen_update_vt100(screen_device &screen, bitmap_ind16 &b
|
||||
// A4 - receiver
|
||||
// A5 - vertical frequency
|
||||
// all other set to 1
|
||||
IRQ_CALLBACK_MEMBER(vt100_state::vt100_irq_callback)
|
||||
IRQ_CALLBACK_MEMBER(vt100_state::vt102_irq_callback)
|
||||
{
|
||||
uint8_t ret = 0xc7 | (m_keyboard_int << 3) | (m_receiver_int << 4) | (m_vertical_int << 5);
|
||||
m_receiver_int = 0;
|
||||
return ret;
|
||||
if (irqline == 0)
|
||||
return m_rstbuf->inta_cb(device, 0);
|
||||
else
|
||||
return 0xff;
|
||||
}
|
||||
|
||||
void vt100_state::machine_start()
|
||||
{
|
||||
m_kbduart->write_tsb(0);
|
||||
m_kbduart->write_eps(1);
|
||||
m_kbduart->write_np(1);
|
||||
m_kbduart->write_nb1(1);
|
||||
m_kbduart->write_nb2(1);
|
||||
m_kbduart->write_cs(1);
|
||||
m_kbduart->write_swe(0);
|
||||
}
|
||||
|
||||
void vt100_state::machine_reset()
|
||||
{
|
||||
m_keyboard_int = 0;
|
||||
m_receiver_int = 0;
|
||||
m_vertical_int = 0;
|
||||
output().set_value("online_led",1);
|
||||
output().set_value("local_led", 0);
|
||||
output().set_value("locked_led",1);
|
||||
output().set_value("l1_led", 1);
|
||||
output().set_value("l2_led", 1);
|
||||
output().set_value("l3_led", 1);
|
||||
output().set_value("l4_led", 1);
|
||||
|
||||
vt100_nvr_latch_w(machine().dummy_space(), 0, 0);
|
||||
}
|
||||
|
||||
@ -233,11 +211,15 @@ READ8_MEMBER( vt100_state::vt100_read_video_ram_r )
|
||||
return m_p_ram[offset];
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER( vt100_state::vert_freq_intr_w )
|
||||
WRITE8_MEMBER(vt100_state::uart_clock_w)
|
||||
{
|
||||
m_vertical_int = (state == ASSERT_LINE) ? 1 : 0;
|
||||
if (state)
|
||||
m_maincpu->set_input_line(0, HOLD_LINE);
|
||||
m_kbduart->write_tcp(BIT(data, 1));
|
||||
m_kbduart->write_rcp(BIT(data, 1));
|
||||
|
||||
if (data == 0 || data == 3)
|
||||
m_keyboard->signal_line_w(m_kbduart->so_r());
|
||||
else
|
||||
m_keyboard->signal_line_w(BIT(data, 0));
|
||||
}
|
||||
|
||||
/* F4 Character Displayer */
|
||||
@ -263,7 +245,7 @@ MACHINE_CONFIG_START(vt100_state::vt100)
|
||||
MCFG_CPU_ADD("maincpu", I8080, XTAL(24'883'200) / 9)
|
||||
MCFG_CPU_PROGRAM_MAP(vt100_mem)
|
||||
MCFG_CPU_IO_MAP(vt100_io)
|
||||
MCFG_CPU_IRQ_ACKNOWLEDGE_DRIVER(vt100_state,vt100_irq_callback)
|
||||
MCFG_CPU_IRQ_ACKNOWLEDGE_DEVICE("rstbuf", rst_pos_buffer_device, inta_cb)
|
||||
|
||||
/* video hardware */
|
||||
MCFG_SCREEN_ADD_MONOCHROME("screen", RASTER, rgb_t::green())
|
||||
@ -281,13 +263,15 @@ MACHINE_CONFIG_START(vt100_state::vt100)
|
||||
MCFG_VT_SET_SCREEN("screen")
|
||||
MCFG_VT_CHARGEN("chargen")
|
||||
MCFG_VT_VIDEO_RAM_CALLBACK(READ8(vt100_state, vt100_read_video_ram_r))
|
||||
MCFG_VT_VIDEO_VERT_FREQ_INTR_CALLBACK(WRITELINE(vt100_state, vert_freq_intr_w))
|
||||
MCFG_VT_VIDEO_VERT_FREQ_INTR_CALLBACK(DEVWRITELINE("rstbuf", rst_pos_buffer_device, rst4_w))
|
||||
MCFG_VT_VIDEO_LBA3_LBA4_CALLBACK(WRITE8(vt100_state, uart_clock_w))
|
||||
MCFG_VT_VIDEO_LBA7_CALLBACK(DEVWRITELINE("nvr", er1400_device, clock_w))
|
||||
|
||||
MCFG_DEVICE_ADD("pusart", I8251, XTAL(24'883'200) / 9)
|
||||
MCFG_I8251_TXD_HANDLER(DEVWRITELINE(RS232_TAG, rs232_port_device, write_txd))
|
||||
MCFG_I8251_DTR_HANDLER(DEVWRITELINE(RS232_TAG, rs232_port_device, write_dtr))
|
||||
MCFG_I8251_RTS_HANDLER(DEVWRITELINE(RS232_TAG, rs232_port_device, write_rts))
|
||||
MCFG_I8251_RXRDY_HANDLER(DEVWRITELINE("rstbuf", rst_pos_buffer_device, rst2_w))
|
||||
|
||||
MCFG_RS232_PORT_ADD(RS232_TAG, default_rs232_devices, nullptr)
|
||||
MCFG_RS232_RXD_HANDLER(DEVWRITELINE("pusart", i8251_device, write_rxd))
|
||||
@ -300,7 +284,14 @@ MACHINE_CONFIG_START(vt100_state::vt100)
|
||||
MCFG_DEVICE_ADD("nvr", ER1400, 0)
|
||||
|
||||
MCFG_DEVICE_ADD("keyboard", VT100_KEYBOARD, 0)
|
||||
MCFG_VT100_KEYBOARD_INT_CALLBACK(WRITELINE(vt100_state, keyboard_int_w))
|
||||
MCFG_VT100_KEYBOARD_SIGNAL_OUT_CALLBACK(DEVWRITELINE("kbduart", ay31015_device, write_si))
|
||||
|
||||
MCFG_DEVICE_ADD("kbduart", AY31015, 0)
|
||||
MCFG_AY31015_WRITE_DAV_CB(DEVWRITELINE("rstbuf", rst_pos_buffer_device, rst1_w))
|
||||
MCFG_AY31015_AUTO_RDAV(true)
|
||||
|
||||
MCFG_DEVICE_ADD("rstbuf", RST_POS_BUFFER, 0)
|
||||
MCFG_RST_BUFFER_INT_CALLBACK(INPUTLINE("maincpu", 0))
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
MACHINE_CONFIG_START(vt100_state::vt180)
|
||||
@ -315,14 +306,18 @@ MACHINE_CONFIG_START(vt100_state::vt102)
|
||||
MCFG_CPU_REPLACE("maincpu", I8085A, XTAL(24'073'400) / 4)
|
||||
MCFG_CPU_PROGRAM_MAP(vt100_mem)
|
||||
MCFG_CPU_IO_MAP(vt100_io)
|
||||
MCFG_CPU_IRQ_ACKNOWLEDGE_DRIVER(vt100_state,vt100_irq_callback)
|
||||
MCFG_CPU_IRQ_ACKNOWLEDGE_DRIVER(vt100_state, vt102_irq_callback)
|
||||
|
||||
MCFG_DEVICE_MODIFY("pusart")
|
||||
MCFG_DEVICE_CLOCK(XTAL(24'073'400) / 8)
|
||||
MCFG_I8251_TXRDY_HANDLER(INPUTLINE("maincpu", I8085_RST75_LINE))
|
||||
|
||||
MCFG_DEVICE_REPLACE("dbrg", COM8116_003, XTAL(24'073'400) / 4)
|
||||
MCFG_COM8116_FR_HANDLER(DEVWRITELINE("pusart", i8251_device, write_rxc))
|
||||
MCFG_COM8116_FT_HANDLER(DEVWRITELINE("pusart", i8251_device, write_txc))
|
||||
|
||||
MCFG_DEVICE_MODIFY("kbduart")
|
||||
MCFG_AY31015_WRITE_TBMT_CB(INPUTLINE("maincpu", I8085_RST65_LINE))
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
/* VT1xx models:
|
||||
|
@ -1,10 +1,12 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Miodrag Milanovic, Jonathan Gevaryahu
|
||||
// copyright-holders:Miodrag Milanovic, Jonathan Gevaryahu, AJR
|
||||
/***************************************************************************
|
||||
|
||||
DEC VT100 keyboard emulation
|
||||
|
||||
TODO: rewrite as externally clocked serial device
|
||||
All data to and from the keyboard is transmitted over a single
|
||||
bidirectional wire. The clock that runs the keyboard's UART and
|
||||
scan counters is multiplexed with the serial data signal.
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
@ -157,11 +159,14 @@ INPUT_PORTS_END
|
||||
|
||||
vt100_keyboard_device::vt100_keyboard_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
|
||||
: device_t(mconfig, VT100_KEYBOARD, tag, owner, clock)
|
||||
, m_int_cb(*this)
|
||||
, m_signal_out_cb(*this)
|
||||
, m_uart(*this, "uart")
|
||||
, m_speaker(*this, "beeper")
|
||||
, m_scan_counter(*this, "counter")
|
||||
, m_key_row(*this, "LINE%X", 0)
|
||||
, m_key_scan(false)
|
||||
, m_key_code(0)
|
||||
, m_signal_line(true)
|
||||
, m_last_signal_change(attotime::zero)
|
||||
, m_last_scan(0)
|
||||
{
|
||||
}
|
||||
|
||||
@ -175,7 +180,12 @@ MACHINE_CONFIG_START(vt100_keyboard_device::device_add_mconfig)
|
||||
MCFG_SOUND_ADD("beeper", BEEP, 786) // 7.945us per serial clock = ~125865.324hz, / 160 clocks per char = ~ 786 hz
|
||||
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50)
|
||||
|
||||
MCFG_TIMER_DRIVER_ADD_PERIODIC("scan_timer", vt100_keyboard_device, scan_callback, attotime::from_hz(800))
|
||||
MCFG_DEVICE_ADD("uart", AY31015, 0)
|
||||
MCFG_AY31015_WRITE_SO_CB(WRITELINE(vt100_keyboard_device, signal_out_w))
|
||||
|
||||
MCFG_DEVICE_ADD("counter", RIPPLE_COUNTER, 0) // 2x 74LS93
|
||||
MCFG_RIPPLE_COUNTER_STAGES(8)
|
||||
MCFG_RIPPLE_COUNTER_COUNT_OUT_CB(WRITE8(vt100_keyboard_device, key_scan_w))
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
|
||||
@ -197,7 +207,7 @@ ioport_constructor vt100_keyboard_device::device_input_ports() const
|
||||
|
||||
void vt100_keyboard_device::device_resolve_objects()
|
||||
{
|
||||
m_int_cb.resolve_safe();
|
||||
m_signal_out_cb.resolve_safe();
|
||||
}
|
||||
|
||||
|
||||
@ -207,76 +217,100 @@ void vt100_keyboard_device::device_resolve_objects()
|
||||
|
||||
void vt100_keyboard_device::device_start()
|
||||
{
|
||||
save_item(NAME(m_key_scan));
|
||||
save_item(NAME(m_key_code));
|
||||
if (!m_uart->started())
|
||||
throw device_missing_dependencies();
|
||||
|
||||
m_uart->write_tsb(0);
|
||||
m_uart->write_eps(1);
|
||||
m_uart->write_np(1);
|
||||
m_uart->write_nb1(1);
|
||||
m_uart->write_nb2(1);
|
||||
m_uart->write_cs(1);
|
||||
m_uart->write_swe(0);
|
||||
|
||||
machine().output().set_value("online_led",1);
|
||||
machine().output().set_value("local_led", 0);
|
||||
machine().output().set_value("locked_led",1);
|
||||
machine().output().set_value("l1_led", 1);
|
||||
machine().output().set_value("l2_led", 1);
|
||||
machine().output().set_value("l3_led", 1);
|
||||
machine().output().set_value("l4_led", 1);
|
||||
|
||||
save_item(NAME(m_signal_line));
|
||||
save_item(NAME(m_last_signal_change));
|
||||
save_item(NAME(m_last_scan));
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// control_w - handle data from CPU to keyboard
|
||||
// (FIXME: this is received through a UART)
|
||||
// signal_line_w - handle external serial input
|
||||
//-------------------------------------------------
|
||||
|
||||
void vt100_keyboard_device::control_w(u8 data)
|
||||
WRITE_LINE_MEMBER(vt100_keyboard_device::signal_line_w)
|
||||
{
|
||||
machine().output().set_value("online_led",BIT(data, 5) ? 0 : 1);
|
||||
machine().output().set_value("local_led", BIT(data, 5));
|
||||
machine().output().set_value("locked_led",BIT(data, 4) ? 0 : 1);
|
||||
machine().output().set_value("l1_led", BIT(data, 3) ? 0 : 1);
|
||||
machine().output().set_value("l2_led", BIT(data, 2) ? 0 : 1);
|
||||
machine().output().set_value("l3_led", BIT(data, 1) ? 0 : 1);
|
||||
machine().output().set_value("l4_led", BIT(data, 0) ? 0 : 1);
|
||||
m_key_scan = BIT(data, 6);
|
||||
m_speaker->set_state(BIT(data, 7));
|
||||
}
|
||||
if (m_signal_line == bool(state))
|
||||
return;
|
||||
|
||||
if (machine().time() > m_last_signal_change + attotime::from_usec(5))
|
||||
m_uart->write_si(m_signal_line);
|
||||
|
||||
//-------------------------------------------------
|
||||
// key_code_r - return the code of the active key
|
||||
// (FIXME: this is delivered through a UART)
|
||||
//-------------------------------------------------
|
||||
if (m_uart->tbmt_r())
|
||||
m_scan_counter->clock_w(state);
|
||||
|
||||
u8 vt100_keyboard_device::key_code_r()
|
||||
{
|
||||
return m_key_code;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// bit_sel -
|
||||
//-------------------------------------------------
|
||||
|
||||
u8 vt100_keyboard_device::bit_sel(u8 data)
|
||||
{
|
||||
if (!BIT(data,7)) return 0x70;
|
||||
if (!BIT(data,6)) return 0x60;
|
||||
if (!BIT(data,5)) return 0x50;
|
||||
if (!BIT(data,4)) return 0x40;
|
||||
if (!BIT(data,3)) return 0x30;
|
||||
if (!BIT(data,2)) return 0x20;
|
||||
if (!BIT(data,1)) return 0x10;
|
||||
if (!BIT(data,0)) return 0x00;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// scan_callback - handle the key scan timer
|
||||
//-------------------------------------------------
|
||||
|
||||
TIMER_DEVICE_CALLBACK_MEMBER(vt100_keyboard_device::scan_callback)
|
||||
{
|
||||
if (m_key_scan)
|
||||
if (state)
|
||||
{
|
||||
for (int i = 0; i < 16; i++)
|
||||
bool dav = m_uart->dav_r();
|
||||
m_uart->write_rdav(!dav);
|
||||
|
||||
if (dav)
|
||||
{
|
||||
u8 code = m_key_row[i]->read();
|
||||
if (code < 0xff)
|
||||
{
|
||||
m_key_code = i | bit_sel(code);
|
||||
m_int_cb(1);
|
||||
break;
|
||||
}
|
||||
u8 data = m_uart->get_received_data();
|
||||
machine().output().set_value("online_led",BIT(data, 5) ? 0 : 1);
|
||||
machine().output().set_value("local_led", BIT(data, 5));
|
||||
machine().output().set_value("locked_led",BIT(data, 4) ? 0 : 1);
|
||||
machine().output().set_value("l1_led", BIT(data, 3) ? 0 : 1);
|
||||
machine().output().set_value("l2_led", BIT(data, 2) ? 0 : 1);
|
||||
machine().output().set_value("l3_led", BIT(data, 1) ? 0 : 1);
|
||||
machine().output().set_value("l4_led", BIT(data, 0) ? 0 : 1);
|
||||
m_speaker->set_state(BIT(data, 7));
|
||||
|
||||
if (BIT(data, 6))
|
||||
m_scan_counter->reset_w(0);
|
||||
}
|
||||
}
|
||||
|
||||
m_uart->write_rcp(state);
|
||||
m_uart->write_tcp(state);
|
||||
|
||||
m_signal_line = bool(state);
|
||||
m_last_signal_change = machine().time();
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// signal_out_w - transmit serial keyboard output
|
||||
//-------------------------------------------------
|
||||
|
||||
WRITE_LINE_MEMBER(vt100_keyboard_device::signal_out_w)
|
||||
{
|
||||
m_signal_out_cb(state);
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// key_scan_w - handle scan counter outputs
|
||||
//-------------------------------------------------
|
||||
|
||||
WRITE8_MEMBER(vt100_keyboard_device::key_scan_w)
|
||||
{
|
||||
if (BIT(data, 0))
|
||||
{
|
||||
u8 input_row = m_key_row[(data >> 1) & 15]->read();
|
||||
if (!BIT(input_row, (data >> 5) & 7))
|
||||
m_uart->set_transmit_data((data >> 1) & 0x7f);
|
||||
}
|
||||
else if (!BIT(data, 7) && BIT(m_last_scan, 7))
|
||||
m_scan_counter->reset_w(1);
|
||||
|
||||
m_last_scan = data;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Miodrag Milanovic, Jonathan Gevaryahu
|
||||
// copyright-holders:Miodrag Milanovic, Jonathan Gevaryahu, AJR
|
||||
/***************************************************************************
|
||||
|
||||
DEC VT100 keyboard emulation
|
||||
@ -11,7 +11,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "machine/timer.h"
|
||||
#include "machine/ay31015.h"
|
||||
#include "machine/ripple_counter.h"
|
||||
#include "sound/beep.h"
|
||||
#include "speaker.h"
|
||||
|
||||
@ -20,8 +21,8 @@
|
||||
// CONFIGURATION MACROS
|
||||
//**************************************************************************
|
||||
|
||||
#define MCFG_VT100_KEYBOARD_INT_CALLBACK(_devcb) \
|
||||
devcb = &downcast<vt100_keyboard_device &>(*device).set_int_callback(DEVCB_##_devcb);
|
||||
#define MCFG_VT100_KEYBOARD_SIGNAL_OUT_CALLBACK(_devcb) \
|
||||
devcb = &downcast<vt100_keyboard_device &>(*device).set_signal_out_callback(DEVCB_##_devcb);
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
@ -37,11 +38,9 @@ public:
|
||||
vt100_keyboard_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
|
||||
|
||||
// configuration
|
||||
template <class Object> devcb_base &set_int_callback(Object &&cb) { return m_int_cb.set_callback(std::forward<Object>(cb)); }
|
||||
template <class Object> devcb_base &set_signal_out_callback(Object &&cb) { return m_signal_out_cb.set_callback(std::forward<Object>(cb)); }
|
||||
|
||||
// accessors (for now)
|
||||
void control_w(u8 data);
|
||||
u8 key_code_r();
|
||||
DECLARE_WRITE_LINE_MEMBER(signal_line_w);
|
||||
|
||||
protected:
|
||||
virtual void device_resolve_objects() override;
|
||||
@ -51,16 +50,19 @@ protected:
|
||||
|
||||
private:
|
||||
// internal helpers
|
||||
static u8 bit_sel(u8 data);
|
||||
DECLARE_WRITE_LINE_MEMBER(signal_out_w);
|
||||
DECLARE_WRITE8_MEMBER(key_scan_w);
|
||||
|
||||
TIMER_DEVICE_CALLBACK_MEMBER(scan_callback);
|
||||
|
||||
devcb_write_line m_int_cb;
|
||||
devcb_write_line m_signal_out_cb;
|
||||
|
||||
required_device<ay31015_device> m_uart;
|
||||
required_device<beep_device> m_speaker;
|
||||
required_device<ripple_counter_device> m_scan_counter;
|
||||
required_ioport_array<16> m_key_row;
|
||||
bool m_key_scan;
|
||||
u8 m_key_code;
|
||||
|
||||
bool m_signal_line;
|
||||
attotime m_last_signal_change;
|
||||
u8 m_last_scan;
|
||||
};
|
||||
|
||||
// device type definition
|
||||
|
@ -78,6 +78,7 @@ vt100_video_device::vt100_video_device(const machine_config &mconfig, device_typ
|
||||
, device_video_interface(mconfig, *this)
|
||||
, m_read_ram(*this)
|
||||
, m_write_vert_freq_intr(*this)
|
||||
, m_write_lba3_lba4(*this)
|
||||
, m_write_lba7(*this)
|
||||
, m_char_rom(*this, finder_base::DUMMY_TAG)
|
||||
, m_palette(*this, "palette")
|
||||
@ -106,12 +107,15 @@ void vt100_video_device::device_start()
|
||||
/* resolve callbacks */
|
||||
m_read_ram.resolve_safe(0);
|
||||
m_write_vert_freq_intr.resolve_safe();
|
||||
m_write_lba3_lba4.resolve();
|
||||
m_write_lba7.resolve_safe();
|
||||
|
||||
// LBA7 is scan line frequency update
|
||||
m_lba7_change_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(vt100_video_device::lba7_change), this));
|
||||
m_lba7_change_timer->adjust(clocks_to_attotime(765), 0, clocks_to_attotime(765));
|
||||
|
||||
m_lba3_change_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(vt100_video_device::lba3_change), this));
|
||||
|
||||
screen().register_vblank_callback(vblank_state_delegate(&vt100_video_device::vblank_callback, this));
|
||||
|
||||
save_item(NAME(m_lba7));
|
||||
@ -892,6 +896,20 @@ TIMER_CALLBACK_MEMBER(vt100_video_device::lba7_change)
|
||||
{
|
||||
m_lba7 = (m_lba7) ? 0 : 1;
|
||||
m_write_lba7(m_lba7);
|
||||
|
||||
if (!m_write_lba3_lba4.isnull())
|
||||
{
|
||||
// The first of every eight low periods of LBA 3 is twice as long
|
||||
m_write_lba3_lba4(2);
|
||||
m_lba3_change_timer->adjust(clocks_to_attotime(90), 3);
|
||||
}
|
||||
}
|
||||
|
||||
TIMER_CALLBACK_MEMBER(vt100_video_device::lba3_change)
|
||||
{
|
||||
m_write_lba3_lba4(param & 3);
|
||||
if (param <= 16)
|
||||
m_lba3_change_timer->adjust(clocks_to_attotime(45), param + 1);
|
||||
}
|
||||
|
||||
|
||||
|
@ -23,6 +23,7 @@ public:
|
||||
|
||||
template <class Object> devcb_base &set_ram_rd_callback(Object &&cb) { return m_read_ram.set_callback(std::forward<Object>(cb)); }
|
||||
template <class Object> devcb_base &set_vert_freq_intr_wr_callback(Object &&cb) { return m_write_vert_freq_intr.set_callback(std::forward<Object>(cb)); }
|
||||
template <class Object> devcb_base &set_lba3_lba4_wr_callback(Object &&cb) { return m_write_lba3_lba4.set_callback(std::forward<Object>(cb)); }
|
||||
template <class Object> devcb_base &set_lba7_wr_callback(Object &&cb) { return m_write_lba7.set_callback(std::forward<Object>(cb)); }
|
||||
|
||||
void set_chargen_tag(const char *tag) { m_char_rom.set_tag(tag); }
|
||||
@ -46,11 +47,13 @@ protected:
|
||||
void recompute_parameters();
|
||||
void vblank_callback(screen_device &screen, bool state);
|
||||
virtual void display_char(bitmap_ind16 &bitmap, uint8_t code, int x, int y, uint8_t scroll_region, uint8_t display_type);
|
||||
TIMER_CALLBACK_MEMBER(lba3_change);
|
||||
TIMER_CALLBACK_MEMBER(lba7_change);
|
||||
virtual void notify_vblank(bool choice) { }
|
||||
|
||||
devcb_read8 m_read_ram;
|
||||
devcb_write_line m_write_vert_freq_intr;
|
||||
devcb_write8 m_write_lba3_lba4;
|
||||
devcb_write_line m_write_lba7;
|
||||
|
||||
int m_lba7;
|
||||
@ -71,7 +74,8 @@ protected:
|
||||
uint8_t m_fill_lines;
|
||||
bool m_is_50hz;
|
||||
bool m_interlaced;
|
||||
emu_timer * m_lba7_change_timer;
|
||||
emu_timer *m_lba3_change_timer;
|
||||
emu_timer *m_lba7_change_timer;
|
||||
|
||||
required_region_ptr<uint8_t> m_char_rom; /* character rom region */
|
||||
required_device<palette_device> m_palette;
|
||||
@ -116,6 +120,9 @@ DECLARE_DEVICE_TYPE(RAINBOW_VIDEO, rainbow_video_device)
|
||||
#define MCFG_VT_VIDEO_VERT_FREQ_INTR_CALLBACK(_write) \
|
||||
devcb = &downcast<vt100_video_device &>(*device).set_vert_freq_intr_wr_callback(DEVCB_##_write);
|
||||
|
||||
#define MCFG_VT_VIDEO_LBA3_LBA4_CALLBACK(_write) \
|
||||
devcb = &downcast<vt100_video_device &>(*device).set_lba3_lba4_wr_callback(DEVCB_##_write);
|
||||
|
||||
#define MCFG_VT_VIDEO_LBA7_CALLBACK(_write) \
|
||||
devcb = &downcast<vt100_video_device &>(*device).set_lba7_wr_callback(DEVCB_##_write);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user