dct11em: machine is now usable

This commit is contained in:
Robbbert 2020-08-01 23:13:13 +10:00
parent 8aae3f8763
commit 47f2b1b161
2 changed files with 170 additions and 34 deletions

View File

@ -6,14 +6,15 @@ DEC DCT11-EM (Evaluation Module)
2010-12-03 Skeleton driver.
System currently works, but with some hacks to replace the unemulated DC319
DLART (Digital Link Asynchronous Receiver/Transmitter).
TODO:
- user LED
- keyboard (not in manual so have to guess)
- HALT and INT buttons (to HALT and PF input lines)
- user LED (it's there but it doesn't work)
- DLART device to be emulated
- hookups between DLART, UART and remaining interrupts
- rs232 terminal
- hookups between DLART (and its DL terminal), UART and remaining interrupts
****************************************************************************/
@ -21,7 +22,9 @@ TODO:
#include "cpu/t11/t11.h"
#include "machine/i8251.h"
#include "machine/i8255.h"
#include "bus/rs232/rs232.h"
#include "machine/clock.h"
#include "machine/terminal.h"
#include "dct11em.lh"
@ -33,10 +36,14 @@ public:
, m_maincpu(*this, "maincpu")
, m_ppi(*this, "ppi")
, m_uart(*this, "uart")
, m_terminal(*this, "terminal")
, m_io_keyboard(*this, "X%u", 0U)
, m_digits(*this, "digit%d", 0U)
{ }
void dct11em(machine_config &config);
DECLARE_INPUT_CHANGED_MEMBER(halt_button);
DECLARE_INPUT_CHANGED_MEMBER(int_button);
private:
void machine_reset() override;
@ -46,17 +53,24 @@ private:
void portc_w(u8);
u8 portc_r();
void irq_encoder(u8, bool);
u8 dlart_r(offs_t);
void dlart_w(offs_t, u8);
void kbd_put(u8 data);
u8 m_term_data;
u8 m_seg_lower;
u8 m_seg_upper;
u8 m_portc;
u16 m_irqs;
bool m_dlart_maintmode;
void mem_map(address_map &map);
required_device<t11_device> m_maincpu;
required_device<i8255_device> m_ppi;
required_device<i8251_device> m_uart;
required_device<generic_terminal_device> m_terminal;
required_ioport_array<5> m_io_keyboard;
output_finder<12> m_digits;
};
@ -67,11 +81,54 @@ void dct11em_state::mem_map(address_map &map)
map(0x1000, 0x1fff).noprw(); // the ram test reads/writes here even though there's no ram
map(0x2000, 0x2fff).ram(); // expansion sockets, 2x 6116
map(0xa000, 0xdfff).rom();
map(0xff20, 0xff27).lw8(NAME([this] (offs_t offset, u8 data) { m_ppi->write(offset>>1, data); }));
map(0xff28, 0xff2b).lw8(NAME([this] (offs_t offset, u8 data) { m_uart->write(offset>>1, data); }));
map(0xff20, 0xff27).nopr().lw8(NAME([this] (offs_t offset, u8 data) { m_ppi->write(offset>>1, data); }));
map(0xff28, 0xff2b).nopr().lw8(NAME([this] (offs_t offset, u8 data) { m_uart->write(offset>>1, data); }));
map(0xff60, 0xff67).lr8(NAME([this] (offs_t offset) { return m_ppi->read(offset>>1); }));
map(0xff68, 0xff6b).lr8(NAME([this] (offs_t offset) { return m_uart->read(offset>>1); }));
//map(0xff70, 0xff7f). // DC309 DLART unemulated device - uart to terminal
//map(0xff70, 0xff7f). // DC319 DLART unemulated device - uart to terminal
map(0xff70, 0xff7f).rw(FUNC(dct11em_state::dlart_r), FUNC(dct11em_state::dlart_w));
}
// dummy routines to pass the DLART test and to talk to the ascii terminal
u8 dct11em_state::dlart_r(offs_t offset)
{
offset >>= 1;
switch (offset)
{
case 0:
if (m_term_data)
return 0xff;
else
return 0xfd;
case 1:
{
u8 ret = m_term_data;
irq_encoder(3, 0); // Release IRQ3
m_term_data = 0;
return ret;
}
default:
return 0xfd;
}
}
void dct11em_state::dlart_w(offs_t offset, u8 data)
{
offset >>= 1;
switch (offset)
{
case 3:
if (m_dlart_maintmode)
m_term_data = data;
else
m_terminal->write(data);
break;
case 2:
m_dlart_maintmode = BIT(data, 4);
break;
default:
break;
}
}
void dct11em_state::porta_w(u8 data)
@ -88,23 +145,22 @@ void dct11em_state::portc_w(u8 data)
if (BIT(data, 3))
{
m_seg_upper = m_seg_lower;
irq_encoder(10, 0);
irq_encoder(10, 0); // Release IRQ10
}
if (data < 6)
{
m_digits[data] = m_seg_lower;
m_digits[data+6] = m_seg_upper;
}
if (data == 10)
output().set_value("led0", 0);
else
if (data == 11)
output().set_value("led0", 1);
output().set_value("led0", (data!=9));
}
u8 dct11em_state::portc_r()
{
return 0;
if (m_portc < 5)
return m_io_keyboard[m_portc]->read();
else
return 0;
}
/*
@ -149,13 +205,59 @@ void dct11em_state::machine_start()
save_item(NAME(m_seg_upper));
save_item(NAME(m_portc));
save_item(NAME(m_irqs));
save_item(NAME(m_term_data));
save_item(NAME(m_dlart_maintmode));
}
/* Input ports */
static INPUT_PORTS_START( dct11em )
PORT_START("X0")
PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("CLR") PORT_CODE(KEYCODE_SPACE)
PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("1/GOLED") PORT_CODE(KEYCODE_1) // Go with LEDs
PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("4/PROTEC") PORT_CODE(KEYCODE_4) // Release protection
PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("7/PC") PORT_CODE(KEYCODE_7)
PORT_START("X1")
PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("0/CANCEL") PORT_CODE(KEYCODE_0) // Cancel breakpoints
PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("2/CONSOL") PORT_CODE(KEYCODE_2) // Start console
PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("5") PORT_CODE(KEYCODE_5)
PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("8/PS") PORT_CODE(KEYCODE_8)
PORT_START("X2")
PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("EXA/ENTER") PORT_CODE(KEYCODE_ENTER)
PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("3/BAUD") PORT_CODE(KEYCODE_3) // Set baud rates
PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("6/SP") PORT_CODE(KEYCODE_6)
PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("9/WP") PORT_CODE(KEYCODE_9)
PORT_START("X3")
PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("ADV") PORT_CODE(KEYCODE_UP)
PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("BAC") PORT_CODE(KEYCODE_DOWN)
PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("REG") PORT_CODE(KEYCODE_R)
PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("ADR") PORT_CODE(KEYCODE_MINUS) // Address
PORT_START("X4")
PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("SST") PORT_CODE(KEYCODE_S) // Single-step
PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("GO") PORT_CODE(KEYCODE_X)
PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("BPT") PORT_CODE(KEYCODE_B) // Breakpoint
PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("FNC") PORT_CODE(KEYCODE_LALT) // Function
PORT_START("X5")
PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("HALT") PORT_CODE(KEYCODE_H) PORT_CHANGED_MEMBER(DEVICE_SELF, dct11em_state, halt_button, 0)
PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("INT") PORT_CODE(KEYCODE_I) PORT_CHANGED_MEMBER(DEVICE_SELF, dct11em_state, int_button, 0)
INPUT_PORTS_END
INPUT_CHANGED_MEMBER(dct11em_state::halt_button)
{
m_maincpu->set_input_line(t11_device::HLT_LINE, newval ? ASSERT_LINE : CLEAR_LINE);
}
INPUT_CHANGED_MEMBER(dct11em_state::int_button)
{
m_maincpu->set_input_line(t11_device::PF_LINE, newval ? ASSERT_LINE : CLEAR_LINE);
}
void dct11em_state::kbd_put(u8 data)
{
m_term_data = data;
irq_encoder(3, 1); // Assert IRQ3
}
void dct11em_state::dct11em(machine_config &config)
{
/* basic machine hardware */
@ -169,17 +271,31 @@ void dct11em_state::dct11em(machine_config &config)
m_ppi->out_pa_callback().set(FUNC(dct11em_state::porta_w)); // segments
// port B - expansion interface
m_ppi->in_pc_callback().set(FUNC(dct11em_state::portc_r)); // keyboard
m_ppi->out_pc_callback().set(FUNC(dct11em_state::portc_w)); // various
m_ppi->out_pc_callback().set(FUNC(dct11em_state::portc_w)); // digits
I8251(config, m_uart, 2'457'600 / 8);
// txc and rxc come from DLART pin 34
m_uart->txd_handler().set("rs232", FUNC(rs232_port_device::write_txd));
m_uart->dtr_handler().set("rs232", FUNC(rs232_port_device::write_dtr));
m_uart->rts_handler().set("rs232", FUNC(rs232_port_device::write_rts));
m_uart->rxrdy_handler().set([this] (bool state) { irq_encoder(7, state); });
m_uart->txrdy_handler().set([this] (bool state) { irq_encoder(6, state); });
clock_device &inta_clock(CLOCK(config, "inta_clock", 614'400 / 768)); // 800Hz, from DLART pin 25
inta_clock.signal_handler().set([this] (bool state) { if (state) irq_encoder(10, 1); });
inta_clock.signal_handler().set([this] (bool state) { if (state) irq_encoder(10, 1); }); // Assert IRQ10
//clock_device &dlart_clock(CLOCK(config, "dlart_clock", 7'500'000 / 4)); --> to DLART CLK pin 32
//clock_device &dlart_clock(CLOCK(config, "dlart_clock", 2'457'600 / 4)); --> to DLART CLK pin 32
//clock_device &uart_clock(CLOCK(config, "uart_clock", 2'457'600 / 8)); --> to UART CLK
clock_device &uart_clock(CLOCK(config, "uart_clock", 2'457'600 / 32)); // from DLART pin 34
uart_clock.signal_handler().set(m_uart, FUNC(i8251_device::write_txc));
uart_clock.signal_handler().append(m_uart, FUNC(i8251_device::write_rxc));
rs232_port_device &rs232(RS232_PORT(config, "rs232", default_rs232_devices, nullptr)); // connection to host mainframe, does nothing for us
rs232.rxd_handler().set(m_uart, FUNC(i8251_device::write_rxd));
rs232.dsr_handler().set(m_uart, FUNC(i8251_device::write_dsr));
rs232.cts_handler().set(m_uart, FUNC(i8251_device::write_cts));
GENERIC_TERMINAL(config, m_terminal, 0); // Main terminal for now
m_terminal->set_keyboard_callback(FUNC(dct11em_state::kbd_put));
}
/* ROM definition */

View File

@ -3,11 +3,21 @@
license:CC0
-->
<mamelayout version="2">
<element name="a_led">
<disk state="0">
<color red="0.0" green="0.75" blue="0.0" />
</disk>
<disk state="1">
<color red="0.0" green="0.15" blue="0.0" />
</disk>
</element>
<element name="digit" defstate="0">
<led7seg>
<color red="0.75" green="0.0" blue="0.0" />
</led7seg>
</element>
<element name="background">
<rect>
<bounds left="0" top="0" right="1" bottom="1" />
@ -16,45 +26,55 @@ license:CC0
</element>
<view name="Default Layout">
<screen index="0">
<bounds x="0" y="0" width="362" height="262" />
</screen>
<!-- Black background -->
<bezel element="background">
<bounds left="97" top="0" right="405" bottom="195" />
<backdrop element="background">
<bounds left="0" top="262" right="274" bottom="350" />
</backdrop>
<bezel name="led0" element="a_led">
<bounds left="300" top="300" right="310" bottom="310" />
</bezel>
<bezel name="digit11" element="digit">
<bounds left="107" top="10" right="155" bottom="90" />
<bounds left="10" top="267" right="44" bottom="305" />
</bezel>
<bezel name="digit10" element="digit">
<bounds left="155" top="10" right="203" bottom="90" />
<bounds left="54" top="267" right="88" bottom="305" />
</bezel>
<bezel name="digit9" element="digit">
<bounds left="203" top="10" right="251" bottom="90" />
<bounds left="98" top="267" right="132" bottom="305" />
</bezel>
<bezel name="digit8" element="digit">
<bounds left="251" top="10" right="299" bottom="90" />
<bounds left="142" top="267" right="176" bottom="305" />
</bezel>
<bezel name="digit7" element="digit">
<bounds left="299" top="10" right="347" bottom="90" />
<bounds left="186" top="267" right="220" bottom="305" />
</bezel>
<bezel name="digit6" element="digit">
<bounds left="347" top="10" right="395" bottom="90" />
<bounds left="230" top="267" right="264" bottom="305" />
</bezel>
<bezel name="digit5" element="digit">
<bounds left="107" top="105" right="155" bottom="185" />
<bounds left="10" top="307" right="44" bottom="345" />
</bezel>
<bezel name="digit4" element="digit">
<bounds left="155" top="105" right="203" bottom="185" />
<bounds left="54" top="307" right="88" bottom="345" />
</bezel>
<bezel name="digit3" element="digit">
<bounds left="203" top="105" right="251" bottom="185" />
<bounds left="98" top="307" right="132" bottom="345" />
</bezel>
<bezel name="digit2" element="digit">
<bounds left="251" top="105" right="299" bottom="185" />
<bounds left="142" top="307" right="176" bottom="345" />
</bezel>
<bezel name="digit1" element="digit">
<bounds left="299" top="105" right="347" bottom="185" />
<bounds left="186" top="307" right="220" bottom="345" />
</bezel>
<bezel name="digit0" element="digit">
<bounds left="347" top="105" right="395" bottom="185" />
<bounds left="230" top="307" right="264" bottom="345" />
</bezel>
</view>
</mamelayout>