New working systems

-------------------
IBM 5100 [Christian Corti, Tom Stepleton]
This commit is contained in:
Patrick Mackinlay 2024-04-01 13:58:53 +07:00
parent 34b7c397c1
commit 85a3c394d2
4 changed files with 839 additions and 0 deletions

488
src/mame/ibm/ibm5100.cpp Normal file
View file

@ -0,0 +1,488 @@
// license:BSD-3-Clause
// copyright-holders:Patrick Mackinlay
/*
* IBM 5100.
*
* Sources:
* - IBM 5100 Maintenance Information Manual, SY31-0405-3, Fourth Edition (October 1979), International Business Machines Corporation
*
* TODO:
* - display registers
* - device address f
* - tape controller
* - printer
* - communications cards
* - expansion feature
* - later models (5110, 5120, 5130)
*/
#include "emu.h"
#include "ibm5100_kbd.h"
#include "cpu/palm/palm.h"
#include "screen.h"
//#define VERBOSE (LOG_GENERAL)
#include "logmacro.h"
namespace {
class ibm5100_state : public driver_device
{
public:
ibm5100_state(machine_config const &mconfig, device_type type, char const *tag)
: driver_device(mconfig, type, tag)
, m_cpu(*this, "cpu")
, m_screen(*this, "screen")
, m_kbd(*this, "kbd")
, m_nxr(*this, { "apl", "basic" })
, m_j2(*this, "j2")
, m_conf(*this, "CONF")
, m_disp(*this, "DISP")
, m_lang(*this, "LANG")
, m_ros(*this, "ros")
{
}
void ibm5100(machine_config &config);
protected:
// driver_device implementation
virtual void machine_start() override;
virtual void machine_reset() override;
void cpu_ros_map(address_map &map);
void cpu_rws_map(address_map &map);
void cpu_ioc_map(address_map &map);
void cpu_iod_map(address_map &map);
u32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, rectangle const &cliprect);
// e2 - ros control card
u8 e2_sts_r();
void e2_ctl_w(u8 data);
u8 e2_r();
void e2_w(u8 data);
// f2 - base i/o card
u8 f2_kbd_sts_r();
void f2_kbd_ctl_w(u8 data);
void da0_ctl_w(u8 data);
void daf_ctl_w(u8 data);
private:
required_device<palm_device> m_cpu;
required_device<screen_device> m_screen;
required_device<ibm5100_keyboard_device> m_kbd;
required_region_ptr_array<u16, 2> m_nxr;
required_region_ptr<u8> m_j2;
required_ioport m_conf;
required_ioport m_disp;
required_ioport m_lang;
memory_view m_ros;
u8 m_getb_bus;
u8 m_e2_ff; // e2 card flip-flops
u8 m_f2_ff; // f2 card flip-flops
u16 m_e2_address;
std::unique_ptr<u16[]> m_rws;
};
enum e2_ff_mask : u8
{
E2_RS = 0x01, // ROS select (0=APL, 1=BASIC/common)
E2_PS = 0x02, // put strobe
E2_B0 = 0x04, // data address bit 0
};
enum f2_ff_mask : u8
{
F2_KIE = 0x01, // keyboard interrupt enable
F2_DO = 0x10, // display off
};
void ibm5100_state::machine_start()
{
// for simplicity allocate maximum 64KiB
m_rws = std::make_unique<u16[]>(0x8000);
save_item(NAME(m_getb_bus));
save_item(NAME(m_e2_ff));
save_item(NAME(m_f2_ff));
save_item(NAME(m_e2_address));
save_pointer(NAME(m_rws), 0x8000);
}
void ibm5100_state::machine_reset()
{
m_e2_ff = 0;
m_f2_ff = 0;
m_e2_address = 0;
// install configured rws
unsigned const rws_cards = (m_conf->read() & 3) + 1;
m_cpu->space(palm_device::AS_RWS).install_ram(0x80, 0x4000 * rws_cards - 1, &m_rws[0x40]);
m_ros[1].install_ram(0x80, 0x4000 * rws_cards - 1, &m_rws[0x40]);
}
void ibm5100_state::cpu_ros_map(address_map &map)
{
map(0x0000, 0xffff).view(m_ros);
m_ros[0](0x0000, 0xffff).rom().region("ros", 0);
}
void ibm5100_state::cpu_rws_map(address_map &map)
{
map.unmap_value_high();
}
void ibm5100_state::cpu_ioc_map(address_map &map)
{
map(0x0, 0x0).w(FUNC(ibm5100_state::da0_ctl_w));
map(0x1, 0x1).rw(FUNC(ibm5100_state::e2_sts_r), FUNC(ibm5100_state::e2_ctl_w));
map(0x2, 0x3).noprw();
map(0x4, 0x4).rw(FUNC(ibm5100_state::f2_kbd_sts_r), FUNC(ibm5100_state::f2_kbd_ctl_w));
// 5 printer r:not used w:control
map(0x6, 0x7).noprw();
// 8 expansion r:status w:control
map(0x9, 0xd).noprw();
// e tape r:status w:control
map(0xf, 0xf).nopr().w(FUNC(ibm5100_state::daf_ctl_w));
}
void ibm5100_state::cpu_iod_map(address_map &map)
{
map.unmap_value_high();
map(0x0, 0x0).noprw();
map(0x1, 0x1).rw(FUNC(ibm5100_state::e2_r), FUNC(ibm5100_state::e2_w));
map(0x2, 0x3).noprw();
map(0x4, 0x4).r(m_kbd, FUNC(ibm5100_keyboard_device::read)).nopw();
// 5 r:printer w:print data
map(0x6, 0x7).noprw();
// 8 expansion r:not used w:data
map(0x9, 0xd).noprw();
// e r:tape data w:tape
map(0xf, 0xf).noprw();
}
void ibm5100_state::ibm5100(machine_config &config)
{
PALM(config, m_cpu, 15'091'200);
m_cpu->set_addrmap(palm_device::AS_ROS, &ibm5100_state::cpu_ros_map);
m_cpu->set_addrmap(palm_device::AS_RWS, &ibm5100_state::cpu_rws_map);
m_cpu->set_addrmap(palm_device::AS_IOC, &ibm5100_state::cpu_ioc_map);
m_cpu->set_addrmap(palm_device::AS_IOD, &ibm5100_state::cpu_iod_map);
m_cpu->getb_bus().set([this](offs_t offset, u8 data) { m_getb_bus = data; });
m_cpu->select_ros().set([this](int state) { m_ros.select(state); });
/*
* Display output is 16 rows of 64 characters. Each character cell is 10x12
* pixels with 8x12 driven from character ROS data. The last two horizontal
* pixels of each character cell line and every other scan line are blank.
*/
SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
m_screen->set_raw(15'091'200, 64*10, 0, 64*10, 16*12*2, 0, 16*12*2);
m_screen->set_screen_update(FUNC(ibm5100_state::screen_update));
IBM5100_KEYBOARD(config, m_kbd);
m_kbd->strobe().set(
[this](int state)
{
if ((m_f2_ff & F2_KIE) && !state)
m_cpu->set_input_line(palm_device::IRPT_REQ3, 0);
});
}
u32 ibm5100_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, rectangle const &cliprect)
{
static rgb_t const c[] = { rgb_t::white(), rgb_t::black() };
// read display switches
u8 const disp = m_disp->read();
bool const reverse = BIT(disp, 0);
bool const n64 = !BIT(disp, 2);
bool const r32 = BIT(disp, 3);
// start with a blank screen
bitmap.fill(c[reverse]);
// then generate characters
auto const rws = util::big_endian_cast<u8 const>(m_rws.get());
for (unsigned char_y = 0; char_y < 16; char_y++)
{
// every other scan line is blank
int const y = screen.visible_area().min_y + char_y * 12 * 2;
// compute offset into rws for each row
offs_t offset = 0x200 + char_y * 64 + (r32 ? 32 : 0);
for (unsigned char_x = 0; char_x < 64; char_x++)
{
int const x = screen.visible_area().min_x + char_x * 10;
// read next character if display is on and normal mode or even column
u8 char_data = 0;
if (!(m_f2_ff & F2_DO) && (n64 || !(char_x & 1)))
char_data = rws[offset++];
// draw 8x12 character cell
for (unsigned cell_y = 0; cell_y < 12; cell_y++)
{
// index into character font data
unsigned const underline = ((cell_y > 7) && BIT(char_data, 7)) ? 4 : 0;
u8 const cell_data = m_j2[(char_data & 0x7f) * 16 + cell_y + underline];
bitmap.pix(y + cell_y * 2, x + 0) = c[BIT(cell_data, 7) ^ reverse];
bitmap.pix(y + cell_y * 2, x + 1) = c[BIT(cell_data, 6) ^ reverse];
bitmap.pix(y + cell_y * 2, x + 2) = c[BIT(cell_data, 5) ^ reverse];
bitmap.pix(y + cell_y * 2, x + 3) = c[BIT(cell_data, 4) ^ reverse];
bitmap.pix(y + cell_y * 2, x + 4) = c[BIT(cell_data, 3) ^ reverse];
bitmap.pix(y + cell_y * 2, x + 5) = c[BIT(cell_data, 2) ^ reverse];
bitmap.pix(y + cell_y * 2, x + 6) = c[BIT(cell_data, 1) ^ reverse];
bitmap.pix(y + cell_y * 2, x + 7) = c[BIT(cell_data, 0) ^ reverse];
}
}
}
return 0;
}
void ibm5100_state::da0_ctl_w(u8 data)
{
LOG("da0_ctl_w 0x%02x (%s)\n", data, machine().describe_context());
// bit 4: 0=display off
if (!BIT(data, 4))
m_f2_ff |= F2_DO;
else
m_f2_ff &= ~F2_DO;
}
u8 ibm5100_state::e2_sts_r()
{
u8 data = 0xff;
if (!machine().side_effects_disabled())
{
data = (m_e2_ff & E2_PS) ? u8(m_e2_address) : (m_e2_address >> 8);
m_e2_ff ^= E2_PS;
}
return data;
}
void ibm5100_state::e2_ctl_w(u8 data)
{
LOG("e2_ctl_w 0x%02x (%s)\n", data, machine().describe_context());
if (!BIT(data, 3))
m_e2_ff &= ~E2_RS;
else if (!BIT(data, 2))
m_e2_ff |= E2_RS;
m_e2_ff &= ~(E2_B0 | E2_PS);
m_e2_address = 0;
}
u8 ibm5100_state::e2_r()
{
u8 data = 0xff;
if (!machine().side_effects_disabled())
{
bool const basic = m_e2_ff & E2_RS;
// check model has selected ROS (all models have common)
if (BIT(m_conf->read(), 2 + basic) || (basic && m_e2_address >= 0x9000))
{
/*
* APL non-executable ROS is addressed with an unshifted 16-bit
* address, giving a 128KiB range; BASIC uses a shifted address,
* giving 64KiB. Even and odd bytes are selected by a flip-flop
* which is toggled with each read.
*/
data = BIT(m_nxr[basic][m_e2_address >> basic], (m_e2_ff & E2_B0) ? 0 : 8, 8);
}
// always increment address for BASIC, only on odd bytes for APL
if (basic || (m_e2_ff & E2_B0))
m_e2_address++;
// toggle even/odd byte flip-flop
m_e2_ff ^= E2_B0;
}
return data;
}
void ibm5100_state::e2_w(u8 data)
{
m_e2_address = (m_e2_address << 8) | data;
if (m_e2_ff & E2_PS)
{
LOG("e2_address 0x%04x (%s)\n", m_e2_address, machine().describe_context());
// data byte even/odd flip-flop is cleared except when BASIC is
// selected and the address is odd
if ((m_e2_ff & E2_RS) && (m_e2_address & 1))
m_e2_ff |= E2_B0;
else
m_e2_ff &= ~E2_B0;
}
// toggle put strobe flip-flop
m_e2_ff ^= E2_PS;
}
u8 ibm5100_state::f2_kbd_sts_r()
{
if (!machine().side_effects_disabled())
{
switch (m_getb_bus)
{
case 0x40:
// keyboard data gate
return m_kbd->read();
case 0x80:
// keyboard status gate
return m_lang->read();
default:
LOG("f2_kbd_sts_r: unknown 0x%02x (%s)\n", m_getb_bus, machine().describe_context());
break;
}
}
return 0xff;
}
void ibm5100_state::f2_kbd_ctl_w(u8 data)
{
LOG("f2_kbd_ctl_w 0x%02x (%s)\n", data, machine().describe_context());
// bit 6: 0=reset and disable keyboard interrupts
if (!BIT(data, 6))
{
m_f2_ff &= ~F2_KIE;
m_cpu->set_input_line(palm_device::IRPT_REQ3, 1);
}
// bit 4: 0=lock keyboard
m_kbd->lock_w(BIT(data, 4));
// bit 1: 0=enable typamatic
// FIXME: inverted?
m_kbd->typamatic_w(BIT(data, 1));
// bit 0: 0=enable keyboard interrupt
if (!BIT(data, 0))
m_f2_ff |= F2_KIE;
else
m_f2_ff &= ~F2_KIE;
}
void ibm5100_state::daf_ctl_w(u8 data)
{
LOG("daf_ctl_w 0x%02x (%s)\n", data, machine().describe_context());
// bit function
// 7 expansion da=8
// 6 tape da=e
// 5 keyboard da=4
// 4 printer da=5
// 3 enable cycle steal
// 2 reset da=b
// 1 reset da=c
// 0 reset da=d
}
ROM_START(ibm5100)
// Executable ROS
ROM_REGION16_BE(0x10000, "ros", 0)
ROM_LOAD("h2.ros", 0x0000, 0x8000, CRC(36d11e3d) SHA1(6be2c0728b88debcd557879c25781a9c7afc5224))
ROM_LOAD("h4.ros", 0x8000, 0x8000, CRC(5d3eceb7) SHA1(e5412914d74e8149ea8a250a6560d1738555ec7e))
// BASIC + Common and Language non-executable ROS
/*
* The common ROS is physically located on the E2 card, and not on the C4
* BASIC card, however it is selected together with the BASIC ROS and
* logically appended to the address space.
*/
ROM_REGION16_BE(0x10000, "basic", 0)
ROM_LOAD("c4.ros", 0x0000, 0x9000, CRC(b1abeb4a) SHA1(e0151fefe63c43c8912599615ddfb7c06f111c72))
ROM_LOAD("e2.ros", 0x9000, 0x4800, CRC(be4289c3) SHA1(008ea7bb25fda94540bf5e02eff5a59bb1c86aac))
ROM_FILL(0xd800, 0x2800, 0xff)
// APL non-executable ROS
ROM_REGION16_BE(0x20000, "apl", 0)
ROM_LOAD("c2.ros", 0x00000, 0x8000, CRC(fba01c70) SHA1(a7dd9b60ba33021d830751df2de5513e0de452f2))
ROM_LOAD("d2.ros", 0x08000, 0x8000, CRC(afb3ba33) SHA1(15292d1082a2d6211fbdbbb0781466506d310954))
ROM_LOAD("d4.ros", 0x10000, 0x8000, CRC(a03570c9) SHA1(5a6e7a5b38b96c8ff47be2572272f8ed0cd31efd))
ROM_FILL(0x18000, 0x8000, 0xff)
// Display Adapter ROS
/*
* This data was hand-made based on the character map in the documentation.
* It was assumed that the first 8 bytes of each character store the upper
* 8x8 cell, then 2x4 byte entries contain the normal and underlined lower
* 4 rows of the total 8x12 cell respectively.
*/
ROM_REGION(0x800, "j2", 0)
ROM_LOAD("j2.ros", 0x000, 0x800, CRC(428e5b66) SHA1(9def68eed9dc2b8f08581387f8b74b49b3faf7e7) BAD_DUMP)
ROM_END
static INPUT_PORTS_START(ibm5100)
PORT_START("CONF")
PORT_CONFNAME(0x0f, 0x0f, "Model")
PORT_CONFSETTING(0x04, "A1 - APL 16K")
PORT_CONFSETTING(0x05, "A2 - APL 32K")
PORT_CONFSETTING(0x06, "A3 - APL 48K")
PORT_CONFSETTING(0x07, "A4 - APL 64K")
PORT_CONFSETTING(0x08, "B1 - BASIC 16K")
PORT_CONFSETTING(0x09, "B2 - BASIC 32K")
PORT_CONFSETTING(0x0a, "B3 - BASIC 48K")
PORT_CONFSETTING(0x0b, "B4 - BASIC 64K")
PORT_CONFSETTING(0x0c, "C1 - APL/BASIC 16K")
PORT_CONFSETTING(0x0d, "C2 - APL/BASIC 32K")
PORT_CONFSETTING(0x0e, "C3 - APL/BASIC 48K")
PORT_CONFSETTING(0x0f, "C4 - APL/BASIC 64K")
PORT_START("DISP")
PORT_CONFNAME(0x01, 0x00, "Reverse")
PORT_CONFSETTING(0x00, "Black on White")
PORT_CONFSETTING(0x01, "White on Black")
PORT_CONFNAME(0x02, 0x00, "Display")
PORT_CONFSETTING(0x00, "Normal")
PORT_CONFSETTING(0x02, "Registers")
PORT_CONFNAME(0x0c, 0x00, "Columns")
PORT_CONFSETTING(0x04, "L32")
PORT_CONFSETTING(0x00, "64")
PORT_CONFSETTING(0x0c, "R32")
PORT_START("LANG")
PORT_CONFNAME(0x40, 0x40, "Language")
PORT_CONFSETTING(0x00, "APL") PORT_CONDITION("CONF", 0x04, EQUALS, 0x04)
PORT_CONFSETTING(0x40, "BASIC") PORT_CONDITION("CONF", 0x08, EQUALS, 0x08)
INPUT_PORTS_END
} // anonymous namespace
/* YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS */
COMP(1975, ibm5100, 0, 0, ibm5100, ibm5100, ibm5100_state, empty_init, "International Business Machines", "IBM 5100", MACHINE_NO_SOUND_HW)

View file

@ -0,0 +1,299 @@
// license:BSD-3-Clause
// copyright-holders:Patrick Mackinlay
/*
* A high level emulation of the IBM 5100 keyboard.
*
* Sources:
* - IBM 5100 Maintenance Information Manual, SY31-0405-3, Fourth Edition (October 1979), International Business Machines Corporation
*
* TODO:
* - missing key names and chars
*
* For columns 0..15, the scan code format is SrrCcccc where:
*
* S = shift modifier (1=active)
* rr = matrix row number
* C = command modifier (1=active)
* cccc = matrix column number
*
* For columns > 15, the scan code format is 1rrccCSc where:
*
* S = shift modifier (0=active)
* rr = matrix row number
* C = command modifier (1=active)
* cc..c = matrix column number
*
* This scheme disallows modifier combinations, with shift taking priority over
* command. Bits 5 and 6 of the scan code are swapped when output.
*
* Regular alpha, numeric and keypad keys are easily mapped 1:1 with a standard
* modern keyboard. Additional keys are mapped by default as follows:
*
* 5100 Key Mapping Rationale
* -------- ------- ---------
* +/- - closest key position, matching shifted symbol
* ×/÷ = closest key position
* / ; moved to row with two non-alpha keys
* = ' moved to row with two non-alpha keys
* [/( [ moved to row with three non-alpha keys, matching unshifted symbol
* ]/) ] moved to row with three non-alpha keys, matching unshifted symbol
* #/@ \ moved to row with three non-alpha keys
* &/$ ` available standard symbol key
*
* l/r/u/d arrow keys conceptual match
* Attention Delete available non-symbol, non-modal key
* Hold Backspace available non-symbol, non-modal key
* Execute Enter conceptual match
* Command L/R Control conceptual match
*/
#include "emu.h"
#include "ibm5100_kbd.h"
#include "machine/keyboard.ipp"
//#define VERBOSE (LOG_GENERAL)
#include "logmacro.h"
DEFINE_DEVICE_TYPE(IBM5100_KEYBOARD, ibm5100_keyboard_device, "ibm5100_keyboard", "IBM 5100 Keyboard")
INPUT_PORTS_START(ibm5100_keyboard)
PORT_START("modifiers")
PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_LSHIFT)
PORT_CODE(KEYCODE_RSHIFT) PORT_NAME("Shift") PORT_CHAR(UCHAR_SHIFT_1)
PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_LCONTROL)
PORT_CODE(KEYCODE_RCONTROL) PORT_NAME("Command") PORT_CHAR(UCHAR_MAMEKEY(LCONTROL))
PORT_START("col.0")
PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_9) PORT_NAME(u8"9 \u2228") PORT_CHAR('9')
PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_I) PORT_NAME(u8"I \u2373") PORT_CHAR('I')
PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_K) PORT_NAME(u8"K '") PORT_CHAR('K') PORT_CHAR('\'')
PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR(';')
PORT_START("col.1")
PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_8) PORT_NAME(u8"8 \u2260") PORT_CHAR('8')
PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_U) PORT_NAME(u8"U \u2193") PORT_CHAR('U')
PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_J) PORT_NAME(u8"J \u2218") PORT_CHAR('J')
PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_M) PORT_NAME(u8"M \u2223") PORT_CHAR('M')
PORT_START("col.2")
PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_EQUALS) PORT_NAME(u8"× ÷") // FIXME: PORT_CHAR?
PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_COLON) PORT_NAME(u8"\u2190 \u2192") // FIXME: PORT_CHAR?
PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR(']') PORT_CHAR(')')
PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_SLASH) PORT_CHAR('/') PORT_CHAR('\\')
PORT_START("col.3")
PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_MINUS) PORT_CHAR('+') PORT_CHAR('-')
PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_P) PORT_NAME(u8"P \u22c6") PORT_CHAR('P')
PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR('[') PORT_CHAR('(')
PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_SPACE) PORT_NAME("Space") PORT_CHAR(UCHAR_MAMEKEY(SPACE))
PORT_START("col.4")
PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_UP) PORT_NAME("Up") PORT_CHAR(UCHAR_MAMEKEY(UP))
PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_8_PAD) PORT_CHAR(UCHAR_MAMEKEY(8_PAD))
PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_5_PAD) PORT_CHAR(UCHAR_MAMEKEY(5_PAD))
PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_2_PAD) PORT_CHAR(UCHAR_MAMEKEY(2_PAD))
PORT_START("col.5")
PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_7_PAD) PORT_CHAR(UCHAR_MAMEKEY(7_PAD))
PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_4_PAD) PORT_CHAR(UCHAR_MAMEKEY(4_PAD))
PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_1_PAD) PORT_CHAR(UCHAR_MAMEKEY(1_PAD))
PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_0_PAD) PORT_CHAR(UCHAR_MAMEKEY(0_PAD))
PORT_START("col.6")
PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_SLASH_PAD) PORT_CHAR(UCHAR_MAMEKEY(SLASH_PAD))
PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_ASTERISK) PORT_NAME("Keypad *") PORT_CHAR(UCHAR_MAMEKEY(ASTERISK))
PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_MINUS_PAD) PORT_CHAR(UCHAR_MAMEKEY(MINUS_PAD))
PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_PLUS_PAD) PORT_CHAR(UCHAR_MAMEKEY(PLUS_PAD))
PORT_START("col.7")
PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_9_PAD) PORT_CHAR(UCHAR_MAMEKEY(9_PAD))
PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_6_PAD) PORT_CHAR(UCHAR_MAMEKEY(6_PAD))
PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_3_PAD) PORT_CHAR(UCHAR_MAMEKEY(3_PAD))
PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_DEL_PAD) PORT_NAME("Keypad .") PORT_CHAR(UCHAR_MAMEKEY(DEL_PAD))
PORT_START("col.8")
PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_6) PORT_NAME(u8"6 \u2265") PORT_CHAR('6')
PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_T) PORT_NAME(u8"T \u223c") PORT_CHAR('T')
PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_G) PORT_NAME(u8"G \u2207") PORT_CHAR('G')
PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_B) PORT_NAME(u8"B \u22a5") PORT_CHAR('B')
PORT_START("col.9")
PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_7) PORT_NAME(u8"7 >") PORT_CHAR('7') PORT_CHAR('>')
PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_Y) PORT_NAME(u8"Y \u2191") PORT_CHAR('Y')
PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_H) PORT_NAME(u8"H \u2206") PORT_CHAR('H')
PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_N) PORT_NAME(u8"N \u22a4") PORT_CHAR('N')
PORT_START("col.a")
PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_4) PORT_NAME(u8"4 \u2264") PORT_CHAR('4')
PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_E) PORT_NAME(u8"E \u220a") PORT_CHAR('E')
PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_D) PORT_NAME(u8"D \u230a") PORT_CHAR('D')
PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_C) PORT_NAME(u8"C \u2229") PORT_CHAR('C')
PORT_START("col.b")
PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_5) PORT_NAME(u8"5 =") PORT_CHAR('5')
PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_R) PORT_NAME(u8"R \u2374") PORT_CHAR('R')
PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_F) PORT_NAME(u8"F _") PORT_CHAR('F') PORT_CHAR('_')
PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_V) PORT_NAME(u8"V \u222a") PORT_CHAR('V')
PORT_START("col.c")
PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_3) PORT_NAME(u8"3 <") PORT_CHAR('3') PORT_CHAR('<')
PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_W) PORT_NAME(u8"W \u2375") PORT_CHAR('W')
PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_S) PORT_NAME(u8"S \u2308") PORT_CHAR('S')
PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_X) PORT_NAME(u8"X \u2283") PORT_CHAR('X')
PORT_START("col.d")
PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_DOWN) PORT_NAME("Down") PORT_CHAR(UCHAR_MAMEKEY(DOWN))
PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_1) PORT_NAME(u8"1 ¨") PORT_CHAR('1')
PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_TILDE) PORT_NAME("&") PORT_CHAR('&') PORT_CHAR('$')
PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_UNUSED)
PORT_START("col.e")
PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_0) PORT_NAME(u8"0 \u2227") PORT_CHAR('0')
PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_O) PORT_NAME(u8"O \u25cb") PORT_CHAR('O')
PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_L) PORT_NAME(u8"L \u2395") PORT_CHAR('L')
PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR(':')
PORT_START("col.f")
PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_2) PORT_NAME(u8"2 \u203e") PORT_CHAR('2')
PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_Q) PORT_NAME(u8"Q ?") PORT_CHAR('Q') PORT_CHAR('?')
PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_A) PORT_NAME(u8"A \u237a") PORT_CHAR('A')
PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_Z) PORT_NAME(u8"Z \u2282") PORT_CHAR('Z')
PORT_START("col.10")
PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_DEL) PORT_NAME("Attention") PORT_CHAR(UCHAR_MAMEKEY(DEL))
PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_RIGHT) PORT_NAME("Right") PORT_CHAR(UCHAR_MAMEKEY(RIGHT))
PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_ENTER)
PORT_CODE(KEYCODE_ENTER_PAD) PORT_NAME("Execute") PORT_CHAR(13)
PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_UNUSED)
PORT_START("col.11")
PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSPACE) PORT_NAME("Hold") PORT_CHAR(8)
PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_LEFT) PORT_NAME("Left") PORT_CHAR(UCHAR_MAMEKEY(LEFT))
PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_QUOTE) PORT_NAME("Equals") PORT_CHAR('=')
PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH) PORT_NAME("# @") PORT_CHAR('#') PORT_CHAR('@')
INPUT_PORTS_END
static const std::pair<u8, u8>typamatic_keys[] =
{
std::make_pair( 3, 3), // space
std::make_pair( 4, 0), // cursor up
std::make_pair(13, 0), // cursor down
std::make_pair(16, 1), // cursor right
std::make_pair(17, 1), // cursor left
};
ibm5100_keyboard_device::ibm5100_keyboard_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
: device_t(mconfig, IBM5100_KEYBOARD, tag, owner, clock)
, device_matrix_keyboard_interface(mconfig, *this
, "col.0", "col.1", "col.2", "col.3", "col.4", "col.5", "col.6", "col.7"
, "col.8", "col.9", "col.a", "col.b", "col.c", "col.d", "col.e", "col.f"
, "col.10", "col.11")
, m_strobe(*this)
, m_modifiers(*this, "modifiers")
, m_lock(false)
{
}
void ibm5100_keyboard_device::device_start()
{
save_item(NAME(m_scan));
save_item(NAME(m_typamatic));
save_item(NAME(m_lock));
}
void ibm5100_keyboard_device::device_reset()
{
m_scan = 0;
m_strobe(1);
m_typamatic = false;
reset_key_state();
start_processing(attotime::from_hz(25'000));
typematic_stop();
}
void ibm5100_keyboard_device::key_make(u8 row, u8 column)
{
if (m_lock)
return;
m_scan = translate(row, column);
LOG("key_make row %d column %d scan 0x%02x\n", row, column, m_scan);
m_strobe(0);
m_strobe(1);
// only some keys have typamatic action
if (std::find(std::begin(typamatic_keys), std::end(typamatic_keys), std::make_pair(row, column)) != std::end(typamatic_keys))
typematic_start(row, column, attotime::from_msec(700), attotime::from_msec(100));
}
void ibm5100_keyboard_device::key_break(u8 row, u8 column)
{
if (typematic_is(row, column))
typematic_stop();
m_scan = 0;
}
void ibm5100_keyboard_device::key_repeat(u8 row, u8 column)
{
if (m_typamatic)
{
m_scan = translate(row, column);
m_strobe(0);
m_strobe(1);
}
}
// column and row are swapped with respect device_matrix_keyboard_interface arguments
u8 ibm5100_keyboard_device::translate(u8 column, u8 row)
{
// compute basic scan code with bits 5 and 6 swapped
u8 data = bitswap<8>(row << 5 | column, 7, 5, 6, 4, 3, 2, 1, 0);
u8 const modifiers = m_modifiers->read();
// modifiers are applied differently for columns > 15
if (column < 16)
{
if (BIT(modifiers, 0))
// shift
data |= 0x80;
else if (BIT(modifiers, 1))
// command
data |= 0x10;
}
else
{
data |= 0x82;
if (BIT(modifiers, 0))
// shift
data &= ~0x02;
else if (BIT(modifiers, 1))
// command
data |= 0x04;
}
return data;
}
void ibm5100_keyboard_device::typamatic_w(int state)
{
m_typamatic = state;
}
void ibm5100_keyboard_device::lock_w(int state)
{
m_lock = !state;
}
ioport_constructor ibm5100_keyboard_device::device_input_ports() const
{
return INPUT_PORTS_NAME(ibm5100_keyboard);
}

View file

@ -0,0 +1,49 @@
// license:BSD-3-Clause
// copyright-holders:Patrick Mackinlay
#ifndef MAME_IBM_IBM5100_KBD_H
#define MAME_IBM_IBM5100_KBD_H
#pragma once
#include "machine/keyboard.h"
class ibm5100_keyboard_device
: public device_t
, protected device_matrix_keyboard_interface<18U>
{
public:
auto strobe() { return m_strobe.bind(); }
ibm5100_keyboard_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock = 0);
u8 read() { return m_scan; }
void typamatic_w(int state);
void lock_w(int state);
protected:
// device_t implementation
virtual ioport_constructor device_input_ports() const override;
virtual void device_start() override;
virtual void device_reset() override;
// device_matrix_keyboard_interface implementation
virtual void key_make(u8 row, u8 column) override;
virtual void key_break(u8 row, u8 column) override;
virtual void key_repeat(u8 row, u8 column) override;
u8 translate(u8 column, u8 row);
private:
devcb_write_line m_strobe;
required_ioport m_modifiers;
u8 m_scan;
bool m_typamatic;
bool m_lock;
};
DECLARE_DEVICE_TYPE(IBM5100_KEYBOARD, ibm5100_keyboard_device)
#endif // MAME_IBM_IBM5100_KBD_H

View file

@ -19798,6 +19798,9 @@ husky // DVW Husky
@source:ibm/ibm3153.cpp
ibm3153 //
@source:ibm/ibm5100.cpp
ibm5100
@source:ibm/ibm5550.cpp
ibm5550 //