mirror of
https://github.com/holub/mame
synced 2025-04-20 23:42:22 +03:00
swtpc8212: get it running, and on the rs232 bus (#5729)
This patch gets it running, and splits it into two front ends, one being a rs232 bus slot so that is can be used as a terminal option. It adds the MCM66750 character generator, and implements the MC6845 row update function. Most of the I/O has been worked out with help from the CT-82 user manual. The various screen formats and the graphics modes appear to be working and plausible. Printer support has been added, and a beeper.
This commit is contained in:
parent
fff889b165
commit
7aa1490a7e
@ -2353,6 +2353,8 @@ if (BUSES["RS232"]~=null) then
|
||||
MAME_DIR .. "src/devices/bus/rs232/xvd701.h",
|
||||
MAME_DIR .. "src/devices/bus/rs232/ie15.cpp",
|
||||
MAME_DIR .. "src/devices/bus/rs232/ie15.h",
|
||||
MAME_DIR .. "src/devices/bus/rs232/swtpc8212.cpp",
|
||||
MAME_DIR .. "src/devices/bus/rs232/swtpc8212.h",
|
||||
}
|
||||
end
|
||||
|
||||
|
@ -2811,6 +2811,18 @@ if (MACHINES["STVCD"]~=null) then
|
||||
}
|
||||
end
|
||||
|
||||
---------------------------------------------------
|
||||
--
|
||||
--@src/devices/machine/swtpc8212.h,MACHINES["SWTPC8212"] = true
|
||||
---------------------------------------------------
|
||||
|
||||
if (MACHINES["SWTPC8212"]~=null) then
|
||||
files {
|
||||
MAME_DIR .. "src/devices/machine/swtpc8212.cpp",
|
||||
MAME_DIR .. "src/devices/machine/swtpc8212.h",
|
||||
}
|
||||
end
|
||||
|
||||
---------------------------------------------------
|
||||
--
|
||||
--
|
||||
|
@ -621,6 +621,7 @@ MACHINES["SMPC"] = true
|
||||
MACHINES["SPG2XX"] = true
|
||||
MACHINES["STVCD"] = true
|
||||
MACHINES["SUN4C_MMU"] = true
|
||||
MACHINES["SWTPC8212"] = true
|
||||
MACHINES["TC0091LVC"] = true
|
||||
MACHINES["TDC1008"] = true
|
||||
--MACHINES["TE7750"] = true
|
||||
|
87
src/devices/bus/rs232/swtpc8212.cpp
Normal file
87
src/devices/bus/rs232/swtpc8212.cpp
Normal file
@ -0,0 +1,87 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:68bit
|
||||
|
||||
#include "emu.h"
|
||||
#include "swtpc8212.h"
|
||||
|
||||
swtpc8212_terminal_device::swtpc8212_terminal_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
||||
: device_t(mconfig, SERIAL_TERMINAL_SWTPC8212, tag, owner, clock)
|
||||
, device_rs232_port_interface(mconfig, *this)
|
||||
, m_swtpc8212(*this, "swtpc8212")
|
||||
, m_flow_control(*this, "FLOW_CONTROL")
|
||||
{
|
||||
}
|
||||
|
||||
void swtpc8212_terminal_device::device_add_mconfig(machine_config &config)
|
||||
{
|
||||
SWTPC8212(config, m_swtpc8212, 0);
|
||||
m_swtpc8212->rs232_conn_txd_handler().set(FUNC(swtpc8212_terminal_device::output_rxd));
|
||||
m_swtpc8212->rs232_conn_rts_handler().set(FUNC(swtpc8212_terminal_device::route_term_rts));
|
||||
m_swtpc8212->rs232_conn_dtr_handler().set(FUNC(swtpc8212_terminal_device::route_term_dtr));
|
||||
}
|
||||
|
||||
INPUT_PORTS_START(swtpc8212_terminal)
|
||||
|
||||
PORT_START("FLOW_CONTROL")
|
||||
PORT_CONFNAME(0x1, 1, "Flow control")
|
||||
PORT_CONFSETTING(0x00, "None") PORT_CHANGED_MEMBER(DEVICE_SELF, swtpc8212_terminal_device, flow_control, 0)
|
||||
PORT_CONFSETTING(0x01, "Terminal DTR to remote CTS") PORT_CHANGED_MEMBER(DEVICE_SELF, swtpc8212_terminal_device, flow_control, 0)
|
||||
|
||||
INPUT_PORTS_END
|
||||
|
||||
ioport_constructor swtpc8212_terminal_device::device_input_ports() const
|
||||
{
|
||||
return INPUT_PORTS_NAME(swtpc8212_terminal);
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER(swtpc8212_terminal_device::input_txd)
|
||||
{
|
||||
m_swtpc8212->rs232_conn_rxd_w(state);
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER(swtpc8212_terminal_device::route_term_rts)
|
||||
{
|
||||
// Loop the terminal RTS output to the terminal CTS input.
|
||||
m_swtpc8212->rs232_conn_cts_w(state);
|
||||
}
|
||||
|
||||
// This terminal uses DTR for hardware flow control.
|
||||
WRITE_LINE_MEMBER(swtpc8212_terminal_device::route_term_dtr)
|
||||
{
|
||||
if (m_flow_control->read())
|
||||
{
|
||||
// Connect the terminal DTR output to CTS at the other end.
|
||||
output_cts(state);
|
||||
}
|
||||
|
||||
// Cache the state, in case the ioport setting changes.
|
||||
m_dtr = state;
|
||||
}
|
||||
|
||||
INPUT_CHANGED_MEMBER(swtpc8212_terminal_device::flow_control)
|
||||
{
|
||||
if (newval)
|
||||
output_cts(m_dtr);
|
||||
else
|
||||
output_cts(0);
|
||||
}
|
||||
|
||||
void swtpc8212_terminal_device::device_start()
|
||||
{
|
||||
save_item(NAME(m_dtr));
|
||||
}
|
||||
|
||||
void swtpc8212_terminal_device::device_reset()
|
||||
{
|
||||
// To the terminal
|
||||
m_swtpc8212->rs232_conn_cts_w(0);
|
||||
|
||||
// To the computer
|
||||
output_rxd(1);
|
||||
output_dcd(0);
|
||||
output_dsr(0);
|
||||
if (!m_flow_control->read())
|
||||
output_cts(0);
|
||||
}
|
||||
|
||||
DEFINE_DEVICE_TYPE(SERIAL_TERMINAL_SWTPC8212, swtpc8212_terminal_device, "swtpc8212_terminal", "SWTPC8212 Terminal")
|
40
src/devices/bus/rs232/swtpc8212.h
Normal file
40
src/devices/bus/rs232/swtpc8212.h
Normal file
@ -0,0 +1,40 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:68bit
|
||||
|
||||
#ifndef MAME_BUS_RS232_SWTPC8212_H
|
||||
#define MAME_BUS_RS232_SWTPC8212_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "rs232.h"
|
||||
#include "machine/swtpc8212.h"
|
||||
|
||||
|
||||
class swtpc8212_terminal_device : public device_t, public device_rs232_port_interface
|
||||
{
|
||||
public:
|
||||
swtpc8212_terminal_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||
|
||||
virtual DECLARE_WRITE_LINE_MEMBER(input_txd) override;
|
||||
|
||||
DECLARE_INPUT_CHANGED_MEMBER(flow_control);
|
||||
|
||||
protected:
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
virtual void device_add_mconfig(machine_config &config) override;
|
||||
virtual ioport_constructor device_input_ports() const override;
|
||||
|
||||
private:
|
||||
required_device<swtpc8212_device> m_swtpc8212;
|
||||
required_ioport m_flow_control;
|
||||
|
||||
DECLARE_WRITE_LINE_MEMBER(route_term_rts);
|
||||
DECLARE_WRITE_LINE_MEMBER(route_term_dtr);
|
||||
|
||||
int m_dtr;
|
||||
};
|
||||
|
||||
DECLARE_DEVICE_TYPE(SERIAL_TERMINAL_SWTPC8212, swtpc8212_terminal_device)
|
||||
|
||||
#endif // MAME_BUS_RS232_SWTPC8212_H
|
@ -10,6 +10,7 @@
|
||||
#include "mps.h"
|
||||
|
||||
#include "bus/rs232/rs232.h"
|
||||
#include "bus/rs232/swtpc8212.h"
|
||||
#include "machine/6850acia.h"
|
||||
|
||||
//**************************************************************************
|
||||
@ -23,11 +24,12 @@ class ss50_mps_device : public device_t, public ss50_card_interface
|
||||
public:
|
||||
// construction/destruction
|
||||
ss50_mps_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
|
||||
: device_t(mconfig, SS50_MPS, tag, owner, clock),
|
||||
ss50_card_interface(mconfig, *this),
|
||||
m_acia(*this, "acia"),
|
||||
m_irq_jumper(*this, "IRQ"),
|
||||
m_rate_jumper(*this, "BAUD")
|
||||
: device_t(mconfig, SS50_MPS, tag, owner, clock)
|
||||
, ss50_card_interface(mconfig, *this)
|
||||
, m_acia(*this, "acia")
|
||||
, m_irq_jumper(*this, "IRQ")
|
||||
, m_rate_jumper(*this, "BAUD")
|
||||
, m_cts_route(*this, "CTS_ROUTE")
|
||||
{
|
||||
}
|
||||
|
||||
@ -48,26 +50,34 @@ protected:
|
||||
|
||||
private:
|
||||
DECLARE_WRITE_LINE_MEMBER(acia_irq_w);
|
||||
DECLARE_WRITE_LINE_MEMBER(route_cts_r);
|
||||
|
||||
required_device<acia6850_device> m_acia;
|
||||
required_ioport m_irq_jumper;
|
||||
required_ioport m_rate_jumper;
|
||||
required_ioport m_cts_route;
|
||||
};
|
||||
|
||||
|
||||
static INPUT_PORTS_START( mps )
|
||||
PORT_START("IRQ")
|
||||
PORT_DIPNAME(1, 0, "IRQ")
|
||||
PORT_DIPSETTING(1, DEF_STR(Off))
|
||||
PORT_DIPSETTING(0, DEF_STR(On))
|
||||
PORT_CONFNAME(1, 0, "IRQ")
|
||||
PORT_CONFSETTING(1, DEF_STR(Off))
|
||||
PORT_CONFSETTING(0, DEF_STR(On))
|
||||
|
||||
PORT_START("BAUD")
|
||||
PORT_DIPNAME(0x1f, 0x1d, "Baud Rate")
|
||||
PORT_DIPSETTING(0x1e, "110")
|
||||
PORT_DIPSETTING(0x1d, "150 / 9600")
|
||||
PORT_DIPSETTING(0x1b, "300")
|
||||
PORT_DIPSETTING(0x17, "600")
|
||||
PORT_DIPSETTING(0x0f, "1200")
|
||||
PORT_CONFNAME(0x1f, 0x1d, "Baud Rate")
|
||||
PORT_CONFSETTING(0x1e, "110")
|
||||
PORT_CONFSETTING(0x1d, "150 / 9600")
|
||||
PORT_CONFSETTING(0x1b, "300")
|
||||
PORT_CONFSETTING(0x17, "600")
|
||||
PORT_CONFSETTING(0x0f, "1200")
|
||||
|
||||
PORT_START("CTS_ROUTE")
|
||||
PORT_CONFNAME(1, 0, "CTS route")
|
||||
PORT_CONFSETTING(0, "Wired low (standard)")
|
||||
PORT_CONFSETTING(1, "Connected through (modified)")
|
||||
|
||||
INPUT_PORTS_END
|
||||
|
||||
|
||||
@ -105,6 +115,8 @@ void ss50_mps_device::device_add_mconfig(machine_config &config)
|
||||
|
||||
rs232_port_device &rs232(RS232_PORT(config, "rs232", default_rs232_devices, "terminal"));
|
||||
rs232.rxd_handler().set(m_acia, FUNC(acia6850_device::write_rxd));
|
||||
rs232.cts_handler().set(FUNC(ss50_mps_device::route_cts_r));
|
||||
rs232.option_add("swtpc8212", SERIAL_TERMINAL_SWTPC8212);
|
||||
rs232.set_option_device_input_defaults("terminal", DEVICE_INPUT_DEFAULTS_NAME(terminal));
|
||||
}
|
||||
|
||||
@ -178,6 +190,13 @@ WRITE_LINE_MEMBER(ss50_mps_device::acia_irq_w)
|
||||
write_irq(state);
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER(ss50_mps_device::route_cts_r)
|
||||
{
|
||||
if (m_cts_route->read())
|
||||
{
|
||||
m_acia->write_cts(state);
|
||||
}
|
||||
}
|
||||
|
||||
// device type definition
|
||||
DEFINE_DEVICE_TYPE_PRIVATE(SS50_MPS, ss50_card_interface, ss50_mps_device, "ss50_mps", "MP-S Serial Interface")
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "mps2.h"
|
||||
|
||||
#include "bus/rs232/rs232.h"
|
||||
#include "bus/rs232/swtpc8212.h"
|
||||
#include "machine/6850acia.h"
|
||||
#include "machine/input_merger.h"
|
||||
|
||||
@ -141,6 +142,7 @@ void ss50_mps2_device::device_add_mconfig(machine_config &config)
|
||||
rs232_upper.rxd_handler().set(m_acia_upper, FUNC(acia6850_device::write_rxd));
|
||||
rs232_upper.cts_handler().set(m_acia_upper, FUNC(acia6850_device::write_cts));
|
||||
rs232_upper.dcd_handler().set(m_acia_upper, FUNC(acia6850_device::write_dcd));
|
||||
rs232_upper.option_add("swtpc8212", SERIAL_TERMINAL_SWTPC8212);
|
||||
rs232_upper.set_option_device_input_defaults("terminal", DEVICE_INPUT_DEFAULTS_NAME(terminal_upper));
|
||||
|
||||
ACIA6850(config, m_acia_lower, 0);
|
||||
@ -152,6 +154,7 @@ void ss50_mps2_device::device_add_mconfig(machine_config &config)
|
||||
rs232_lower.rxd_handler().set(m_acia_lower, FUNC(acia6850_device::write_rxd));
|
||||
rs232_lower.cts_handler().set(m_acia_lower, FUNC(acia6850_device::write_cts));
|
||||
rs232_lower.dcd_handler().set(m_acia_lower, FUNC(acia6850_device::write_dcd));
|
||||
rs232_lower.option_add("swtpc8212", SERIAL_TERMINAL_SWTPC8212);
|
||||
rs232_lower.set_option_device_input_defaults("terminal", DEVICE_INPUT_DEFAULTS_NAME(terminal_lower));
|
||||
|
||||
INPUT_MERGER_ANY_HIGH(config, "irq").output_handler().set(FUNC(ss50_mps2_device::write_irq));
|
||||
|
582
src/devices/machine/swtpc8212.cpp
Normal file
582
src/devices/machine/swtpc8212.cpp
Normal file
@ -0,0 +1,582 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:AJR,68bit
|
||||
/****************************************************************************
|
||||
|
||||
Driver for Southwest Technical Products video terminal 8210.
|
||||
|
||||
MC6802P, 2xMC6821P, INS8250N, MCM66750, MC6845P, bank of 8 dips, crystals
|
||||
17.0748 (video), 1.8432 (cpu/uart). On the back is a 25-pin RS-232 port, and a
|
||||
25-pin printer port.
|
||||
|
||||
The 8212 terminal appears similar in design to the CT-82 terminal for which
|
||||
there is some documentation and a user guide. In particular it appears closest
|
||||
to the 'Version B1'. There was also a 8209 terminal with an 9 inch CRT versus
|
||||
the 12 inch CRT in the 8212. This terminal has also been labeled at the
|
||||
CT8200. http://www.swtpc.com/mholley/CT_82/CT82_Index.htm
|
||||
|
||||
The 8212 has three CRT controller configurations:
|
||||
1. 82 x 20 characters, with a height of 14 scan lines.
|
||||
2. 82 x 24 characters, with a height of 12 scan lines.
|
||||
3. 92 x 22 characters, with a height of 12 scan lines.
|
||||
|
||||
There are two character generators:
|
||||
1. The MCM66750 with 7x9 sized characters with some descending by 3 lines
|
||||
giving an effective 7x12 sized character set.
|
||||
2. An EPROM defining 8x16 sized characters for which only 12 scan lines are
|
||||
used, and this is used for the graphics mode.
|
||||
|
||||
These appear to map onto the CT-82 screen formats options as follows:
|
||||
Format I: 82 by 20, MCM66750 character set. Ctrl-\ crtl-Q
|
||||
Format II: 82 by 24, MCM66750 character set. Ctrl-\ crtl-R
|
||||
Format III: 82 by 20, EPROM character set. Ctrl-\ crtl-S
|
||||
Format IV: 82 by 24, EPROM character set. Ctrl-\ crtl-T
|
||||
Graphics: 92 by 22, EPROM character set. Ctrl-] crtl-V
|
||||
|
||||
The semi-graphics character set is defined in an EPROM, and that EPROM defines
|
||||
these characters but here is a brief description of the graphics codes. It
|
||||
includes graphics characters that support a two by three pixel array per
|
||||
character. The codes 0x20 to 0x5f remain ASCII characters. The codes 0x00 to
|
||||
0x1f have the following graphics encoding:
|
||||
|
||||
000xxxxx
|
||||
----------
|
||||
| D0 | D3 |
|
||||
-----------
|
||||
| D1 | D4 |
|
||||
-----------
|
||||
| D2 | 0 |
|
||||
-----------
|
||||
|
||||
The codes 0x60 to 0x7f have the following graphics encoding:
|
||||
|
||||
011xxxxx
|
||||
-----------
|
||||
| D0 | D3 |
|
||||
-----------
|
||||
| D1 | D4 |
|
||||
-----------
|
||||
| D2 | 1 |
|
||||
-----------
|
||||
|
||||
The terminal includes a parallel printer output and Ctrl-] Ctrl-K enables
|
||||
printer pass-through and Ctrl-] Ctrl-G disables pass-through.
|
||||
|
||||
The terminal appears to include light pen support, and the positions is read
|
||||
via Ctrl-] Ctrl-B, TODO.
|
||||
|
||||
The numeric keypad is separte to the keyboard, returning a separate 4 bit code
|
||||
and strobe. The CT-82 documentation suggests that the order of the bits on the
|
||||
keypad bus is reversed. Photos of the 8212 show a 16 key keypad. The ROM has a
|
||||
table starting at 0xb8e4 that maps the keypad code read from PIA 0 Port A bits
|
||||
4 to 7 into a character code. This table has two vectors of 16 bytes, and the
|
||||
first 16 are used when in the 'cursor' mode and the later 16 are uses when in
|
||||
the 'numeric' keypad mode. In the 'cursor' mode, four of the keys are
|
||||
underfined. TODO the labels of all the keypad keys could not be read from the
|
||||
photo found, so could use a better photo of the keypad and an update here.
|
||||
|
||||
The keypad codes in the ROM appear consistent with the CT-82
|
||||
documentation. However the codes for the left and right cursor keys are not
|
||||
consistent with a UniFlex termcap entry for the 'ct8200' which has the right
|
||||
cursor code being 0x1d and the left cursor code being 0x1e. The standard CT-82
|
||||
codes of Ctrl-D and Ctrl-I for these keys are not good choices for a 'Unix'
|
||||
like terminal and it appears likely that there is either a ROM revision making
|
||||
this trivial change to better work with UniFlex or that people did patch the
|
||||
keypad codes. The keypad codes are single character codes so there is very
|
||||
limit room to add more, and some of keys were not even assigned a code,
|
||||
history! A ROM patch assigning code friendlier to Unix is included in this
|
||||
emulator.
|
||||
|
||||
A glitch in the interaction of the keyboard and the keypad has been noted. When
|
||||
typing fast on the keyboard a character may not be sent. Then if another key is
|
||||
typed on the keyboard the unsent code is lost. But if another key is typed on
|
||||
the keypad then the unsent keyboard code is then sent and the keypad code is
|
||||
lost. The firmware has a one character send buffer. TODO This might be a
|
||||
firmware issue, or might be a problem with the emulation of the PIA or UART or
|
||||
the keyboard or keypad strobes etc.
|
||||
|
||||
TODO A generic keyboard is used. Might need some work to get a better keyboard
|
||||
emulation. The CT-82 documentation mentions a 'Break' key.
|
||||
|
||||
TODO A generic 'beep' is used. Might want to compare this with the actual 8212
|
||||
to better emulate the sound.
|
||||
|
||||
TODO the CB2 input of 'pia0' at address 0x0080 is polled by the firmware, and
|
||||
it is the first input checked in the ISR. On a CB2 interrupt the ISR checks
|
||||
for a 'break' condition on the UART and if not then it clears the UART OUT1
|
||||
output. There are other suggestions in the firmware that the OUT1 and OUT2
|
||||
UART lines are being driven. The operation here is unknown?
|
||||
|
||||
TODO Confirm the CPU XTAL. The terminal emulation appears slugish compared
|
||||
with the documented claims, the hardware flow control is needed even at 9600
|
||||
and it does not operate at 38400 as documented. The CT82 manual mentions an
|
||||
optional 4MHz crystal and that would run the CPU at 1MHz which is the rated
|
||||
speed for the CPU and perhaps the 8212 uses that 4MHz XTAL or at least
|
||||
something faster the current 1.8432MHz XTAL?
|
||||
|
||||
The terminfo database does not appear to have an entry for this terminal, and
|
||||
the following is offered that attempts to use the features of the terminal that
|
||||
map to ncurses and this helped testing and it appears to run the ncurses tests
|
||||
and some utilities ok. The cursor keys are set for the patched ROM option. Keep
|
||||
in mind that it is an ASCII terminal so try an ISO-8859-1 locale, and also that
|
||||
it has no tabs so it needs tab to space translation.
|
||||
|
||||
swtp|ct8212|southwest technical products ct8212,
|
||||
cols#82, lines#24,
|
||||
bel=^G, civis=^E, clear=^L, cnorm=^U, cr=\r,
|
||||
cub=^\^D%p1%c, cub1=^D, cud=^\^B%p1%c, cud1=^B,
|
||||
cuf1=^R, cup=^K%p2%{32}%+%c%p1%{32}%+%c,
|
||||
cuu=^\^A%p1%c, cuu1=^A, dch1=^\^H, dl1=^Z, ed=^V, el=^F,
|
||||
el1=^\^F, home=^P, hpa=^\^W%p1%{32}%+%c, ich1=^\^X,
|
||||
il1=^\^Y, ind=^N,
|
||||
is2=^_^A$<250>^\^R$<50>^^^D^^^T^_^J\040^^^G^^^O^^^Z^]^W^I^R,
|
||||
kbs=^H, kcub1=^B, kcud1=^N, kcuf1=^F, kcuu1=^P, khome=^A,
|
||||
ll=^C, mc4=^]^G, mc5=^]^K, nel=\r\n, ri=^O, rmir=, rmso=^^^F,
|
||||
smir=, smso=^^^V, vpa=^\^G%p1%{32}%+%c,
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "machine/swtpc8212.h"
|
||||
#include "machine/input_merger.h"
|
||||
#include "screen.h"
|
||||
#include "speaker.h"
|
||||
|
||||
swtpc8212_device::swtpc8212_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
|
||||
: device_t(mconfig, type, tag, owner, clock)
|
||||
, m_maincpu(*this, "maincpu")
|
||||
, m_pia0(*this, "pia0")
|
||||
, m_pia1(*this, "pia1")
|
||||
, m_uart(*this, "uart")
|
||||
, m_crtc(*this, "crtc")
|
||||
, m_chargen1(*this, "chargen1")
|
||||
, m_chargen2(*this, "chargen2")
|
||||
, m_video_ram(*this, "videoram")
|
||||
, m_config(*this, "CONFIG")
|
||||
, m_keypad(*this, "KEYPAD")
|
||||
, m_one_stop_bit(*this, "ONE_STOP_BIT")
|
||||
, m_bell_timer(nullptr)
|
||||
, m_beeper(*this, "beeper")
|
||||
, m_printer(*this, "printer")
|
||||
, m_rs232_conn_txd_handler(*this)
|
||||
, m_rs232_conn_dtr_handler(*this)
|
||||
, m_rs232_conn_rts_handler(*this)
|
||||
{
|
||||
}
|
||||
|
||||
swtpc8212_device::swtpc8212_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
||||
: swtpc8212_device(mconfig, SWTPC8212, tag, owner, clock)
|
||||
{
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(swtpc8212_device::latch_w)
|
||||
{
|
||||
// Bits 0 to 3 control outputs that are intended to control and tape
|
||||
// 'read' and 'punch' operations. These are strobes, about 10usec, and
|
||||
// intended to trigger on the falling edge.
|
||||
//
|
||||
// Bit 0 - Read on output
|
||||
// Bit 1 - Read off output
|
||||
// Bit 2 - Punch on output
|
||||
// Bit 3 - Punch off output
|
||||
|
||||
// Bit 4 - ?? usually high
|
||||
// Bit 5 - ?? usually low
|
||||
|
||||
// Bits 6 and 7 change with the screen format.
|
||||
//
|
||||
// Bit 6 is zero for formats I and II, and one for formats III and IV
|
||||
// and for the graphics format. Assume this selects between the
|
||||
// characters sets, so formats III and IV might use an alternative
|
||||
// custom text character set.
|
||||
//
|
||||
// Bit 6 - character set: 0 - standard; 1 - alternate/graphics.
|
||||
//
|
||||
// Bit 7 is zero in formats I, II, III, and IV, and one for the
|
||||
// graphics format. Assume this controls the horizontal
|
||||
// inter-character gap, eliminating the gap for the graphics format.
|
||||
//
|
||||
// Bit 7 - character width: 0 - 9 dots; 1 - 8 dots.
|
||||
//
|
||||
if (BIT(data, 7) == 0)
|
||||
m_crtc->set_char_width(9);
|
||||
else
|
||||
m_crtc->set_char_width(8);
|
||||
|
||||
m_latch_data = data;
|
||||
}
|
||||
|
||||
|
||||
READ8_MEMBER(swtpc8212_device::pia0_pa_r)
|
||||
{
|
||||
// PA0 controls the 'duplex' mode, the echoing back of characters, and
|
||||
// appears to connect to a switch on the outer casing.
|
||||
//
|
||||
// PA1 On the CT-82 this enabled or disabled use of an optional ROM,
|
||||
// but that function is disabled in the 8212, and this is probably
|
||||
// unused.
|
||||
//
|
||||
// PA2 is Jumper B, and PA3 is Jumper A.
|
||||
uint8_t config = m_config->read();
|
||||
|
||||
return (m_keypad_data << 4) | config;
|
||||
}
|
||||
|
||||
READ8_MEMBER(swtpc8212_device::pia0_pb_r)
|
||||
{
|
||||
return m_keyboard_data;
|
||||
}
|
||||
|
||||
void swtpc8212_device::keyboard_put(uint8_t data)
|
||||
{
|
||||
m_keyboard_data = data;
|
||||
// Triggers on the falling edge.
|
||||
m_pia0->cb1_w(ASSERT_LINE);
|
||||
m_pia0->cb1_w(CLEAR_LINE);
|
||||
m_pia0->cb1_w(ASSERT_LINE);
|
||||
}
|
||||
|
||||
INPUT_CHANGED_MEMBER(swtpc8212_device::keypad_changed)
|
||||
{
|
||||
uint16_t keys = m_keypad->read();
|
||||
uint8_t n;
|
||||
|
||||
for (n = 0; n < 16; n++)
|
||||
{
|
||||
if (BIT(keys, n))
|
||||
break;
|
||||
}
|
||||
|
||||
m_keypad_data = n;
|
||||
|
||||
if (newval)
|
||||
{
|
||||
m_pia0->ca1_w(ASSERT_LINE);
|
||||
m_pia0->ca1_w(CLEAR_LINE);
|
||||
m_pia0->ca1_w(ASSERT_LINE);
|
||||
}
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER(swtpc8212_device::pia0_ca2_w)
|
||||
{
|
||||
if (state == 0)
|
||||
{
|
||||
m_beeper->set_state(1);
|
||||
m_bell_timer->reset(attotime::from_msec(250));
|
||||
}
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(swtpc8212_device::pia1_pa_w)
|
||||
{
|
||||
// External parallel printer data output.
|
||||
m_printer_data = data;
|
||||
}
|
||||
|
||||
READ_LINE_MEMBER(swtpc8212_device::pia1_ca1_r)
|
||||
{
|
||||
// External parallel printer busy input.
|
||||
return 0;
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER(swtpc8212_device::pia1_ca2_w)
|
||||
{
|
||||
// External parallel printer data ready.
|
||||
|
||||
// Trigger on the falling edge.
|
||||
if (m_printer_data_ready == 1 && state == 0)
|
||||
{
|
||||
m_printer->output(m_printer_data);
|
||||
// Toggle the printer busy line as the software waits for a
|
||||
// falling edge.
|
||||
m_pia1->ca1_w(CLEAR_LINE);
|
||||
m_pia1->ca1_w(ASSERT_LINE);
|
||||
m_pia1->ca1_w(CLEAR_LINE);
|
||||
}
|
||||
m_printer_data_ready = state;
|
||||
}
|
||||
|
||||
MC6845_UPDATE_ROW(swtpc8212_device::update_row)
|
||||
{
|
||||
int x = 0;
|
||||
uint8_t *chargen = BIT(m_latch_data, 6) == 0 ? m_chargen1 : m_chargen2;
|
||||
|
||||
for (int column = 0; column < x_count; column++)
|
||||
{
|
||||
uint8_t code = m_video_ram[(ma + column) & 0x07ff];
|
||||
int dcursor = (column == cursor_x);
|
||||
|
||||
offs_t address = ra < 16 ? (code & 0x7f) | (ra & 0x0f) << 7 : 0;
|
||||
uint8_t data = chargen[address];
|
||||
uint8_t intensity = BIT(code, 7);
|
||||
|
||||
for (int bit = 0; bit < 8; bit++)
|
||||
{
|
||||
int dout = BIT(data, 7);
|
||||
uint32_t font_color = 0;
|
||||
if ((dcursor ^ dout) && de)
|
||||
{
|
||||
if (intensity)
|
||||
font_color = rgb_t(0x10, 0xff, 0x10);
|
||||
else
|
||||
font_color = rgb_t(0x00, 0xd0, 0x00);
|
||||
}
|
||||
bitmap.pix32(y, x++) = font_color;
|
||||
data <<= 1;
|
||||
}
|
||||
|
||||
// Gap between characters
|
||||
if (BIT(m_latch_data, 7) == 0)
|
||||
x++;
|
||||
}
|
||||
}
|
||||
|
||||
void swtpc8212_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
|
||||
{
|
||||
switch (id)
|
||||
{
|
||||
case BELL_TIMER_ID:
|
||||
m_beeper->set_state(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER(swtpc8212_device::rs232_conn_dcd_w)
|
||||
{
|
||||
m_uart->dcd_w(state);
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER(swtpc8212_device::rs232_conn_dsr_w)
|
||||
{
|
||||
m_uart->dsr_w(state);
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER(swtpc8212_device::rs232_conn_ri_w)
|
||||
{
|
||||
m_uart->ri_w(state);
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER(swtpc8212_device::rs232_conn_cts_w)
|
||||
{
|
||||
m_uart->cts_w(state);
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER(swtpc8212_device::rs232_conn_rxd_w)
|
||||
{
|
||||
m_uart->rx_w(state);
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER(swtpc8212_device::write_txd)
|
||||
{
|
||||
m_rs232_conn_txd_handler(state);
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER(swtpc8212_device::write_dtr)
|
||||
{
|
||||
m_rs232_conn_dtr_handler(state);
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER(swtpc8212_device::write_rts)
|
||||
{
|
||||
m_rs232_conn_rts_handler(state);
|
||||
}
|
||||
|
||||
void swtpc8212_device::device_resolve_objects()
|
||||
{
|
||||
m_rs232_conn_dtr_handler.resolve_safe();
|
||||
m_rs232_conn_rts_handler.resolve_safe();
|
||||
m_rs232_conn_txd_handler.resolve_safe();
|
||||
}
|
||||
|
||||
void swtpc8212_device::device_start()
|
||||
{
|
||||
m_bell_timer = timer_alloc(BELL_TIMER_ID);
|
||||
|
||||
save_item(NAME(m_latch_data));
|
||||
save_item(NAME(m_keyboard_data));
|
||||
save_item(NAME(m_printer_data));
|
||||
save_item(NAME(m_printer_data_ready));
|
||||
}
|
||||
|
||||
void swtpc8212_device::device_reset()
|
||||
{
|
||||
m_keyboard_data = 0;
|
||||
m_pia0->cb1_w(ASSERT_LINE);
|
||||
m_keypad_data = 0;
|
||||
m_pia0->ca1_w(ASSERT_LINE);
|
||||
|
||||
m_latch_data = 0x1f;
|
||||
|
||||
m_beeper->set_state(0);
|
||||
|
||||
m_printer_data = 0;
|
||||
m_printer_data_ready = 1;
|
||||
m_pia1->ca1_w(CLEAR_LINE);
|
||||
|
||||
if (m_one_stop_bit->read())
|
||||
{
|
||||
// Patch the firmware to use one stop bit.
|
||||
uint8_t* program = memregion("program")->base();
|
||||
program[0x01ad] = 0x02;
|
||||
}
|
||||
}
|
||||
|
||||
void swtpc8212_device::mem_map(address_map &map)
|
||||
{
|
||||
map(0x0000, 0x007f).ram();
|
||||
map(0x0080, 0x0083).rw("pia0", FUNC(pia6821_device::read), FUNC(pia6821_device::write));
|
||||
map(0x0088, 0x0088).w("crtc", FUNC(mc6845_device::address_w));
|
||||
map(0x0089, 0x0089).rw("crtc", FUNC(mc6845_device::register_r), FUNC(mc6845_device::register_w));
|
||||
map(0x008c, 0x008c).w(FUNC(swtpc8212_device::latch_w));
|
||||
map(0x0090, 0x0097).rw("uart", FUNC(ins8250_device::ins8250_r), FUNC(ins8250_device::ins8250_w));
|
||||
map(0x0098, 0x009b).rw("pia1", FUNC(pia6821_device::read), FUNC(pia6821_device::write));
|
||||
map(0x4000, 0x47ff).mirror(0x1800).ram().share(m_video_ram);
|
||||
map(0xb800, 0xbfff).rom().region("program", 0);
|
||||
map(0xc000, 0xc7ff).mirror(0x3800).rom().region("program", 0x800);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
INPUT_PORTS_START(swtpc8212)
|
||||
|
||||
PORT_START("KEYPAD")
|
||||
PORT_BIT(0x0002U, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("7 / Form") PORT_CHANGED_MEMBER(DEVICE_SELF, swtpc8212_device, keypad_changed, 0)
|
||||
PORT_BIT(0x0004U, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("8 / Xmit") PORT_CHANGED_MEMBER(DEVICE_SELF, swtpc8212_device, keypad_changed, 0)
|
||||
PORT_BIT(0x0001U, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("9 / ??") PORT_CHANGED_MEMBER(DEVICE_SELF, swtpc8212_device, keypad_changed, 0)
|
||||
PORT_BIT(0x0008U, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("\xC3\xB7 / ??") PORT_CHANGED_MEMBER(DEVICE_SELF, swtpc8212_device, keypad_changed, 0)
|
||||
PORT_BIT(0x0200U, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("4 / Scroll Up") PORT_CODE(KEYCODE_PGDN) PORT_CHANGED_MEMBER(DEVICE_SELF, swtpc8212_device, keypad_changed, 0)
|
||||
PORT_BIT(0x0400U, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("5 / \xE2\x86\x91") PORT_CODE(KEYCODE_UP) PORT_CHANGED_MEMBER(DEVICE_SELF, swtpc8212_device, keypad_changed, 0)
|
||||
PORT_BIT(0x0100U, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("6 / Insert") PORT_CODE(KEYCODE_0_PAD) PORT_CHANGED_MEMBER(DEVICE_SELF, swtpc8212_device, keypad_changed, 0)
|
||||
PORT_BIT(0x0800U, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("\xC3\x97 / ??") PORT_CHANGED_MEMBER(DEVICE_SELF, swtpc8212_device, keypad_changed, 0)
|
||||
PORT_BIT(0x0020U, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("1 / \xE2\x86\x90") PORT_CODE(KEYCODE_LEFT) PORT_CHANGED_MEMBER(DEVICE_SELF, swtpc8212_device, keypad_changed, 0)
|
||||
PORT_BIT(0x0040U, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("2 / Home") PORT_CODE(KEYCODE_HOME) PORT_CHANGED_MEMBER(DEVICE_SELF, swtpc8212_device, keypad_changed, 0)
|
||||
PORT_BIT(0x0010U, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("3 / \xE2\x86\x92") PORT_CODE(KEYCODE_RIGHT) PORT_CHANGED_MEMBER(DEVICE_SELF, swtpc8212_device, keypad_changed, 0)
|
||||
PORT_BIT(0x0080U, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("- / LF") PORT_CHANGED_MEMBER(DEVICE_SELF, swtpc8212_device, keypad_changed, 0)
|
||||
PORT_BIT(0x2000U, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("0 / Scroll Down") PORT_CODE(KEYCODE_PGUP) PORT_CHANGED_MEMBER(DEVICE_SELF, swtpc8212_device, keypad_changed, 0)
|
||||
PORT_BIT(0x4000U, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("0 / \xE2\x86\x93") PORT_CODE(KEYCODE_DOWN) PORT_CHANGED_MEMBER(DEVICE_SELF, swtpc8212_device, keypad_changed, 0)
|
||||
PORT_BIT(0x1000U, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME(". / Delete") PORT_CODE(KEYCODE_DEL_PAD) PORT_CHANGED_MEMBER(DEVICE_SELF, swtpc8212_device, keypad_changed, 0)
|
||||
PORT_BIT(0x8000U, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("+ / CR") PORT_CHANGED_MEMBER(DEVICE_SELF, swtpc8212_device, keypad_changed, 0)
|
||||
|
||||
PORT_START("DIP_SWITCHES")
|
||||
PORT_DIPNAME(0x1f, 0x19, "Baud Rate") PORT_DIPLOCATION("DIP:4,3,2,1,0")
|
||||
PORT_DIPSETTING(0x04, "110")
|
||||
PORT_DIPSETTING(0x0a, "300")
|
||||
PORT_DIPSETTING(0x0d, "600")
|
||||
PORT_DIPSETTING(0x0f, "1200")
|
||||
PORT_DIPSETTING(0x12, "2400")
|
||||
PORT_DIPSETTING(0x16, "4800")
|
||||
PORT_DIPSETTING(0x18, "7200")
|
||||
PORT_DIPSETTING(0x19, "9600")
|
||||
PORT_DIPSETTING(0x1c, "19200")
|
||||
PORT_DIPSETTING(0x1f, "38400")
|
||||
PORT_DIPNAME(0x20, 0x00, "Mode switch") PORT_DIPLOCATION("DIP:5")
|
||||
PORT_DIPSETTING(0x00, "Conversational")
|
||||
PORT_DIPSETTING(0x20, "Page edit")
|
||||
PORT_DIPNAME(0x40, 0x00, "No Parity") PORT_DIPLOCATION("DIP:6")
|
||||
PORT_DIPSETTING(0x00, "No Parity")
|
||||
PORT_DIPSETTING(0x40, "Parity")
|
||||
PORT_DIPNAME(0x80, 0x00, "Parity Select") PORT_DIPLOCATION("DIP:7")
|
||||
PORT_DIPSETTING(0x00, "Odd or Mark")
|
||||
PORT_DIPSETTING(0x80, "Even or Space")
|
||||
|
||||
PORT_START("CONFIG")
|
||||
PORT_CONFNAME(0x01, 0x01, "Duplex")
|
||||
PORT_CONFSETTING(0x00, "Full duplex")
|
||||
PORT_CONFSETTING(0x01, "Half duplex")
|
||||
PORT_CONFNAME(0x02, 0x00, "Option ROM (Not used)")
|
||||
PORT_CONFSETTING(0x00, DEF_STR(On))
|
||||
PORT_CONFSETTING(0x02, DEF_STR(Off))
|
||||
PORT_CONFNAME(0x04, 0x04, "Parity Select (Jumper B)")
|
||||
PORT_CONFSETTING(0x00, "Odd or Even (On)")
|
||||
PORT_CONFSETTING(0x04, "Mark or Space (Off)")
|
||||
PORT_CONFNAME(0x08, 0x08, "Data bits (Jumper A)")
|
||||
PORT_CONFSETTING(0x00, "7 bit data (On)")
|
||||
PORT_CONFSETTING(0x08, "8 bit data (Off)")
|
||||
|
||||
PORT_START("ONE_STOP_BIT")
|
||||
PORT_CONFNAME(1, 1, "One stop bit patch")
|
||||
PORT_CONFSETTING(0, "No")
|
||||
PORT_CONFSETTING(1, "Yes - apply patch")
|
||||
|
||||
INPUT_PORTS_END
|
||||
|
||||
|
||||
ROM_START( swtpc8212 )
|
||||
ROM_REGION( 0x1000, "program", 0 )
|
||||
ROM_LOAD( "8224g_ver.1.1_6oct80.ic1", 0x0000, 0x0800, CRC(7d7f3c21) SHA1(f7e6e20b36a1c724a4e348bc784d0b7b5fb462a3) )
|
||||
ROM_LOAD( "8224g_ver.1.1_6oct80.ic2", 0x0800, 0x0800, CRC(2b118c22) SHA1(5fa031c834c7c582d5715764941499fcef51f477) )
|
||||
|
||||
ROM_REGION( 0x0800, "chargen1", 0 )
|
||||
ROM_LOAD( "mcm66750.rom", 0x0000, 0x0800, CRC(aedc2830) SHA1(49ce17d5b5cefb24e89ed3fd59887a652501b919) )
|
||||
ROM_REGION( 0x0800, "chargen2", 0 )
|
||||
ROM_LOAD( "grafix_8x12_22aug80.bin", 0x0000, 0x0800, CRC(a525ed65) SHA1(813d2e85ddb258c5b032b959e695ad33200cbcc4) )
|
||||
ROM_END
|
||||
|
||||
void swtpc8212_device::device_add_mconfig(machine_config &config)
|
||||
{
|
||||
M6802(config, m_maincpu, 1.8432_MHz_XTAL);
|
||||
m_maincpu->set_addrmap(AS_PROGRAM, &swtpc8212_device::mem_map);
|
||||
|
||||
INPUT_MERGER_ANY_HIGH(config, "mainirq").output_handler().set_inputline(m_maincpu, M6802_IRQ_LINE);
|
||||
|
||||
// PA - various jumpers and keypad inputs.
|
||||
// PB - parallel keyboard data input.
|
||||
// CA1 - parallel keypad input strobe.
|
||||
// CA2 - output, bell.
|
||||
// CB1 - parallel keyboard input strobe.
|
||||
// CB2 ??
|
||||
PIA6821(config, m_pia0);
|
||||
m_pia0->readpa_handler().set(FUNC(swtpc8212_device::pia0_pa_r));
|
||||
m_pia0->readpb_handler().set(FUNC(swtpc8212_device::pia0_pb_r));
|
||||
m_pia0->ca2_handler().set(FUNC(swtpc8212_device::pia0_ca2_w));
|
||||
m_pia0->irqa_handler().set("mainirq", FUNC(input_merger_device::in_w<0>));
|
||||
m_pia0->irqb_handler().set("mainirq", FUNC(input_merger_device::in_w<1>));
|
||||
|
||||
// PA - parallel printer data outputs.
|
||||
// PB - various config inputs.
|
||||
// CA1 - parallel printer, 'busy' input.
|
||||
// CA2 - parallel printer, 'data ready' output.
|
||||
// CB1 - Handshake input?
|
||||
// CB2 - Handshake output?
|
||||
PIA6821(config, m_pia1);
|
||||
m_pia1->writepa_handler().set(FUNC(swtpc8212_device::pia1_pa_w));
|
||||
m_pia1->readca1_handler().set(FUNC(swtpc8212_device::pia1_ca1_r));
|
||||
m_pia1->ca2_handler().set(FUNC(swtpc8212_device::pia1_ca2_w));
|
||||
m_pia1->readpb_handler().set_ioport("DIP_SWITCHES");
|
||||
|
||||
INS8250(config, m_uart, 1.8432_MHz_XTAL);
|
||||
m_uart->out_tx_callback().set(FUNC(swtpc8212_device::write_txd));
|
||||
m_uart->out_dtr_callback().set(FUNC(swtpc8212_device::write_dtr));
|
||||
m_uart->out_rts_callback().set(FUNC(swtpc8212_device::write_rts));
|
||||
m_uart->out_int_callback().set("mainirq", FUNC(input_merger_device::in_w<2>));
|
||||
|
||||
screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
|
||||
screen.set_raw(17.0748_MHz_XTAL, 918, 0, 738, 310, 0, 280);
|
||||
screen.set_screen_update("crtc", FUNC(mc6845_device::screen_update));
|
||||
|
||||
MC6845(config, m_crtc, 17.0748_MHz_XTAL / 9);
|
||||
m_crtc->set_char_width(9);
|
||||
m_crtc->set_screen("screen");
|
||||
m_crtc->set_show_border_area(false);
|
||||
m_crtc->set_update_row_callback(FUNC(swtpc8212_device::update_row));
|
||||
|
||||
generic_keyboard_device &keyboard(GENERIC_KEYBOARD(config, "keyboard", 0));
|
||||
keyboard.set_keyboard_callback(FUNC(swtpc8212_device::keyboard_put));
|
||||
|
||||
SPEAKER(config, "bell").front_center();
|
||||
BEEP(config, m_beeper, 2000);
|
||||
m_beeper->add_route(ALL_OUTPUTS, "bell", 0.25);
|
||||
|
||||
PRINTER(config, m_printer, 0);
|
||||
}
|
||||
|
||||
ioport_constructor swtpc8212_device::device_input_ports() const
|
||||
{
|
||||
return INPUT_PORTS_NAME(swtpc8212);
|
||||
}
|
||||
|
||||
const tiny_rom_entry *swtpc8212_device::device_rom_region() const
|
||||
{
|
||||
return ROM_NAME(swtpc8212);
|
||||
}
|
||||
|
||||
DEFINE_DEVICE_TYPE(SWTPC8212, swtpc8212_device, "swtpc8212_device", "SWTPC8212")
|
102
src/devices/machine/swtpc8212.h
Normal file
102
src/devices/machine/swtpc8212.h
Normal file
@ -0,0 +1,102 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:AJR,68bit
|
||||
|
||||
#ifndef MAME_MACHINE_SWTPC8212_H
|
||||
#define MAME_MACHINE_SWTPC8212_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cpu/m6800/m6800.h"
|
||||
#include "imagedev/printer.h"
|
||||
#include "machine/6821pia.h"
|
||||
#include "machine/ins8250.h"
|
||||
#include "machine/terminal.h"
|
||||
#include "video/mc6845.h"
|
||||
|
||||
INPUT_PORTS_EXTERN(swtpc8212);
|
||||
|
||||
|
||||
class swtpc8212_device : public device_t
|
||||
{
|
||||
public:
|
||||
swtpc8212_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||
|
||||
DECLARE_INPUT_CHANGED_MEMBER(keypad_changed);
|
||||
|
||||
// Interface to a RS232 connection.
|
||||
auto rs232_conn_txd_handler() { return m_rs232_conn_txd_handler.bind(); }
|
||||
auto rs232_conn_dtr_handler() { return m_rs232_conn_dtr_handler.bind(); }
|
||||
auto rs232_conn_rts_handler() { return m_rs232_conn_rts_handler.bind(); }
|
||||
DECLARE_WRITE_LINE_MEMBER(rs232_conn_dcd_w);
|
||||
DECLARE_WRITE_LINE_MEMBER(rs232_conn_dsr_w);
|
||||
DECLARE_WRITE_LINE_MEMBER(rs232_conn_ri_w);
|
||||
DECLARE_WRITE_LINE_MEMBER(rs232_conn_cts_w);
|
||||
DECLARE_WRITE_LINE_MEMBER(rs232_conn_rxd_w);
|
||||
|
||||
protected:
|
||||
swtpc8212_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
|
||||
|
||||
virtual void device_resolve_objects() override;
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
|
||||
|
||||
virtual void device_add_mconfig(machine_config &config) override;
|
||||
virtual ioport_constructor device_input_ports() const override;
|
||||
virtual const tiny_rom_entry *device_rom_region() const override;
|
||||
|
||||
private:
|
||||
enum
|
||||
{
|
||||
BELL_TIMER_ID = 1
|
||||
};
|
||||
|
||||
void mem_map(address_map &map);
|
||||
|
||||
required_device<m6802_cpu_device> m_maincpu;
|
||||
required_device<pia6821_device> m_pia0;
|
||||
required_device<pia6821_device> m_pia1;
|
||||
required_device<ins8250_device> m_uart;
|
||||
required_device<mc6845_device> m_crtc;
|
||||
required_region_ptr<u8> m_chargen1;
|
||||
required_region_ptr<u8> m_chargen2;
|
||||
required_shared_ptr<u8> m_video_ram;
|
||||
required_ioport m_config;
|
||||
required_ioport m_keypad;
|
||||
required_ioport m_one_stop_bit;
|
||||
emu_timer *m_bell_timer;
|
||||
required_device<beep_device> m_beeper;
|
||||
required_device<printer_image_device> m_printer;
|
||||
|
||||
devcb_write_line m_rs232_conn_txd_handler;
|
||||
devcb_write_line m_rs232_conn_dtr_handler;
|
||||
devcb_write_line m_rs232_conn_rts_handler;
|
||||
|
||||
MC6845_UPDATE_ROW(update_row);
|
||||
|
||||
DECLARE_WRITE8_MEMBER(latch_w);
|
||||
uint8_t m_latch_data;
|
||||
|
||||
DECLARE_READ8_MEMBER(pia0_pa_r);
|
||||
DECLARE_READ8_MEMBER(pia0_pb_r);
|
||||
DECLARE_WRITE_LINE_MEMBER(pia0_ca2_w);
|
||||
|
||||
DECLARE_WRITE8_MEMBER(pia1_pa_w);
|
||||
DECLARE_READ_LINE_MEMBER(pia1_ca1_r);
|
||||
DECLARE_WRITE_LINE_MEMBER(pia1_ca2_w);
|
||||
|
||||
uint8_t m_keyboard_data;
|
||||
uint8_t m_keypad_data;
|
||||
uint8_t m_printer_data;
|
||||
uint8_t m_printer_data_ready;
|
||||
|
||||
void keyboard_put(uint8_t data);
|
||||
|
||||
DECLARE_WRITE_LINE_MEMBER(write_txd);
|
||||
DECLARE_WRITE_LINE_MEMBER(write_dtr);
|
||||
DECLARE_WRITE_LINE_MEMBER(write_rts);
|
||||
};
|
||||
|
||||
DECLARE_DEVICE_TYPE(SWTPC8212, swtpc8212_device)
|
||||
|
||||
#endif // MAME_MACHINE_SWTPC8212_H
|
@ -1,124 +1,53 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:AJR
|
||||
/****************************************************************************
|
||||
// copyright-holders:68bit
|
||||
/***************************************************************************
|
||||
|
||||
Skeleton driver for Southwest Technical Products video terminal.
|
||||
SWTPC 8212 Video Terminal
|
||||
|
||||
Front end interfacing the terminal device to a MAME RS232 port.
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
//#include "bus/rs232/rs232.h"
|
||||
#include "cpu/m6800/m6800.h"
|
||||
#include "machine/6821pia.h"
|
||||
#include "machine/input_merger.h"
|
||||
#include "machine/ins8250.h"
|
||||
#include "video/mc6845.h"
|
||||
#include "screen.h"
|
||||
|
||||
#include "machine/swtpc8212.h"
|
||||
#include "bus/rs232/rs232.h"
|
||||
|
||||
class swtpc8212_state : public driver_device
|
||||
{
|
||||
public:
|
||||
swtpc8212_state(const machine_config &mconfig, device_type type, const char *tag)
|
||||
: driver_device(mconfig, type, tag)
|
||||
, m_maincpu(*this, "maincpu")
|
||||
, m_chargen(*this, "chargen")
|
||||
{
|
||||
}
|
||||
swtpc8212_state(const machine_config &mconfig, device_type type, const char *tag) :
|
||||
driver_device(mconfig, type, tag)
|
||||
, m_swtpc8212(*this, "swtpc8212")
|
||||
, m_rs232(*this, "rs232")
|
||||
{ }
|
||||
|
||||
void swtpc8212(machine_config &mconfig);
|
||||
void swtpc8212(machine_config &config);
|
||||
|
||||
private:
|
||||
MC6845_UPDATE_ROW(update_row);
|
||||
|
||||
void mem_map(address_map &map);
|
||||
|
||||
required_device<cpu_device> m_maincpu;
|
||||
required_region_ptr<u8> m_chargen;
|
||||
required_device<swtpc8212_device> m_swtpc8212;
|
||||
required_device<rs232_port_device> m_rs232;
|
||||
};
|
||||
|
||||
MC6845_UPDATE_ROW(swtpc8212_state::update_row)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void swtpc8212_state::mem_map(address_map &map)
|
||||
{
|
||||
map(0x0000, 0x007f).ram();
|
||||
map(0x0080, 0x0083).rw("pia0", FUNC(pia6821_device::read), FUNC(pia6821_device::write));
|
||||
map(0x0088, 0x0088).w("crtc", FUNC(mc6845_device::address_w));
|
||||
map(0x0089, 0x0089).rw("crtc", FUNC(mc6845_device::register_r), FUNC(mc6845_device::register_w));
|
||||
map(0x0090, 0x0097).rw("uart", FUNC(ins8250_device::ins8250_r), FUNC(ins8250_device::ins8250_w));
|
||||
map(0x0098, 0x009b).rw("pia1", FUNC(pia6821_device::read), FUNC(pia6821_device::write));
|
||||
map(0x4800, 0x4fff).ram();
|
||||
map(0xb800, 0xbfff).rom().region("program", 0);
|
||||
map(0xc000, 0xc7ff).mirror(0x3800).rom().region("program", 0x800);
|
||||
}
|
||||
|
||||
|
||||
static INPUT_PORTS_START(swtpc8212)
|
||||
PORT_START("DSW")
|
||||
PORT_DIPNAME(0x01, 0x00, DEF_STR(Unknown))
|
||||
PORT_DIPSETTING(0x01, DEF_STR(Off))
|
||||
PORT_DIPSETTING(0x00, DEF_STR(On))
|
||||
PORT_DIPNAME(0x02, 0x00, DEF_STR(Unknown))
|
||||
PORT_DIPSETTING(0x02, DEF_STR(Off))
|
||||
PORT_DIPSETTING(0x00, DEF_STR(On))
|
||||
PORT_DIPNAME(0x04, 0x00, DEF_STR(Unknown))
|
||||
PORT_DIPSETTING(0x04, DEF_STR(Off))
|
||||
PORT_DIPSETTING(0x00, DEF_STR(On))
|
||||
PORT_DIPNAME(0x08, 0x00, DEF_STR(Unknown))
|
||||
PORT_DIPSETTING(0x08, DEF_STR(Off))
|
||||
PORT_DIPSETTING(0x00, DEF_STR(On))
|
||||
PORT_DIPNAME(0x10, 0x00, DEF_STR(Unknown))
|
||||
PORT_DIPSETTING(0x10, DEF_STR(Off))
|
||||
PORT_DIPSETTING(0x00, DEF_STR(On))
|
||||
PORT_DIPNAME(0x20, 0x00, DEF_STR(Unknown))
|
||||
PORT_DIPSETTING(0x20, DEF_STR(Off))
|
||||
PORT_DIPSETTING(0x00, DEF_STR(On))
|
||||
PORT_DIPNAME(0x40, 0x00, DEF_STR(Unknown))
|
||||
PORT_DIPSETTING(0x40, DEF_STR(Off))
|
||||
PORT_DIPSETTING(0x00, DEF_STR(On))
|
||||
PORT_DIPNAME(0x80, 0x00, DEF_STR(Unknown))
|
||||
PORT_DIPSETTING(0x80, DEF_STR(Off))
|
||||
PORT_DIPSETTING(0x00, DEF_STR(On))
|
||||
INPUT_PORTS_END
|
||||
|
||||
void swtpc8212_state::swtpc8212(machine_config &config)
|
||||
{
|
||||
M6802(config, m_maincpu, 1.8432_MHz_XTAL);
|
||||
m_maincpu->set_addrmap(AS_PROGRAM, &swtpc8212_state::mem_map);
|
||||
SWTPC8212(config, m_swtpc8212, 0);
|
||||
|
||||
INPUT_MERGER_ANY_HIGH(config, "mainirq").output_handler().set_inputline(m_maincpu, M6802_IRQ_LINE);
|
||||
RS232_PORT(config, m_rs232, default_rs232_devices, nullptr);
|
||||
m_rs232->dcd_handler().set(m_swtpc8212, FUNC(swtpc8212_device::rs232_conn_dcd_w));
|
||||
m_rs232->dsr_handler().set(m_swtpc8212, FUNC(swtpc8212_device::rs232_conn_dsr_w));
|
||||
m_rs232->ri_handler().set(m_swtpc8212, FUNC(swtpc8212_device::rs232_conn_ri_w));
|
||||
m_rs232->cts_handler().set(m_swtpc8212, FUNC(swtpc8212_device::rs232_conn_cts_w));
|
||||
m_rs232->rxd_handler().set(m_swtpc8212, FUNC(swtpc8212_device::rs232_conn_rxd_w));
|
||||
|
||||
pia6821_device &pia0(PIA6821(config, "pia0"));
|
||||
pia0.irqa_handler().set("mainirq", FUNC(input_merger_device::in_w<0>));
|
||||
pia0.irqb_handler().set("mainirq", FUNC(input_merger_device::in_w<1>));
|
||||
|
||||
PIA6821(config, "pia1");
|
||||
|
||||
ins8250_device &uart(INS8250(config, "uart", 1.8432_MHz_XTAL));
|
||||
uart.out_int_callback().set("mainirq", FUNC(input_merger_device::in_w<2>));
|
||||
|
||||
screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
|
||||
screen.set_raw(17.0748_MHz_XTAL, 918, 0, 738, 310, 0, 280);
|
||||
screen.set_screen_update("crtc", FUNC(mc6845_device::screen_update));
|
||||
|
||||
mc6845_device &crtc(MC6845(config, "crtc", 17.0748_MHz_XTAL / 9));
|
||||
crtc.set_char_width(9);
|
||||
crtc.set_screen("screen");
|
||||
crtc.set_show_border_area(false);
|
||||
crtc.set_update_row_callback(FUNC(swtpc8212_state::update_row));
|
||||
m_swtpc8212->rs232_conn_txd_handler().set(m_rs232, FUNC(rs232_port_device::write_txd));
|
||||
m_swtpc8212->rs232_conn_dtr_handler().set(m_rs232, FUNC(rs232_port_device::write_dtr));
|
||||
m_swtpc8212->rs232_conn_rts_handler().set(m_rs232, FUNC(rs232_port_device::write_rts));
|
||||
}
|
||||
|
||||
|
||||
ROM_START( swtpc8212 ) // MC6802P, 2xMC6821P, INS8250N, MCM66750, MC6845P, bank of 8 dips, crystals 17.0748 (video), 1.8432 (cpu/uart). On the back is a 25-pin RS-232 port, and a 25-pin printer port.
|
||||
ROM_REGION( 0x1000, "program", 0 )
|
||||
ROM_LOAD( "8224g_ver.1.1_6oct80.ic1", 0x0000, 0x0800, CRC(7d7f3c21) SHA1(f7e6e20b36a1c724a4e348bc784d0b7b5fb462a3) )
|
||||
ROM_LOAD( "8224g_ver.1.1_6oct80.ic2", 0x0800, 0x0800, CRC(2b118c22) SHA1(5fa031c834c7c582d5715764941499fcef51f477) )
|
||||
|
||||
ROM_REGION( 0x0800, "chargen", 0 )
|
||||
ROM_LOAD( "grafix_8x12_22aug80.bin", 0x0000, 0x0800, CRC(a525ed65) SHA1(813d2e85ddb258c5b032b959e695ad33200cbcc4) )
|
||||
ROM_START(swtpc8212)
|
||||
ROM_END
|
||||
|
||||
COMP(1980, swtpc8212, 0, 0, swtpc8212, swtpc8212, swtpc8212_state, empty_init, "Southwest Technical Products", "SWTPC 8212 Video Terminal", MACHINE_IS_SKELETON)
|
||||
// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS
|
||||
COMP(1980, swtpc8212, 0, 0, swtpc8212, 0, swtpc8212_state, empty_init, "Southwest Technical Products", "SWTPC 8212 Video Terminal", 0 )
|
||||
|
@ -37298,7 +37298,7 @@ swtpc09i // S09, DC4 Floppy + PIA IDE SBUG rom - FLEX
|
||||
swtpc09u // S09, DMF2 Floppy UNIBUG rom - UniFLEX
|
||||
|
||||
@source:swtpc8212.cpp
|
||||
swtpc8212 //
|
||||
swtpc8212 // Terminal
|
||||
|
||||
@source:swyft.cpp
|
||||
swyft //
|
||||
|
Loading…
Reference in New Issue
Block a user