mirror of
https://github.com/holub/mame
synced 2025-06-05 04:16:28 +03:00
eispc.cpp: Split out of the Ericsson PC (epc) from pc.cpp and added a serial keyboard
This commit is contained in:
parent
dd737543f0
commit
dda15d1b6d
@ -1119,6 +1119,7 @@ function linkProjects_mame_mess(_target, _subtarget)
|
||||
"entex",
|
||||
"epoch",
|
||||
"epson",
|
||||
"ericsson",
|
||||
"exidy",
|
||||
"fairch",
|
||||
"fairlight",
|
||||
@ -2182,6 +2183,13 @@ files {
|
||||
MAME_DIR .. "src/mame/machine/qx10kbd.h",
|
||||
}
|
||||
|
||||
createMESSProjects(_target, _subtarget, "ericsson")
|
||||
files {
|
||||
MAME_DIR .. "src/mame/drivers/eispc.cpp",
|
||||
MAME_DIR .. "src/mame/machine/eispc_kb.cpp",
|
||||
MAME_DIR .. "src/mame/machine/eispc_kb.h",
|
||||
}
|
||||
|
||||
createMESSProjects(_target, _subtarget, "exidy")
|
||||
files {
|
||||
MAME_DIR .. "src/mame/machine/sorcerer.cpp",
|
||||
|
962
src/mame/drivers/eispc.cpp
Normal file
962
src/mame/drivers/eispc.cpp
Normal file
@ -0,0 +1,962 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Joakim Larsson Edström
|
||||
/***************************************************************************************************
|
||||
*
|
||||
* Ericsson Information Systems PC "compatibles"
|
||||
*
|
||||
* The Ericsson PC was the the first original Ericsson design for the office PC market replacing the
|
||||
* Step/One which was an OEM:ed clone of the Matsushita Mybrain 3000 (see myb3k.cpp driver).
|
||||
*
|
||||
**************************************************************
|
||||
* Ericsson PC
|
||||
*------------
|
||||
* Links: https://youtu.be/6uilOdMJc24
|
||||
* Form Factor: Desktop
|
||||
* CPU: 8088 @ 4.77MHz
|
||||
* RAM: 256K
|
||||
* Bus: 6x ISA
|
||||
* Video: Monchrome or Color 80x25 character mode. 320x200 and 640x400 grahics modes
|
||||
* Display: Orange Gas Plasma (GP) display
|
||||
* Mass storage: 2 x 5.25" 360K or 1 20Mb HDD
|
||||
* On board ports: Beeper,
|
||||
* Ports: serial, parallel
|
||||
* Internal Options: Up to 640K RAM through add-on RAM card
|
||||
* Misc: The hardware was not 100% PC compatible so non BIOS based software would not run. 50.000+ units sold
|
||||
*
|
||||
* TODO:
|
||||
* - Add keyboard, first HLE as in pc.cpp and then LLE when the keyboard controller is dumped
|
||||
* - Add the on-board FDC and boot DOS 1.xx
|
||||
* - Complete the Ericsson 1070 MDA ISA board and test all the graphics modes inclusing 640x400 (aka HR)
|
||||
* - Add the Ericsson 1065 HDC and boot from a hard drive
|
||||
*
|
||||
* Credits: The driver code is inspired from m24.cpp, myb3k.cpp and genpc.cpp. Information about the EPC has
|
||||
* been contributed by many, mainly the people at Dalby Computer museum http://www.datormuseum.se/
|
||||
* A dead pcb was donated by rfka01 and rom dumps by ZnaxQue@sweclockers.com
|
||||
*
|
||||
************************************************************************************************************/
|
||||
/*
|
||||
Links:
|
||||
------
|
||||
|
||||
*/
|
||||
|
||||
#include "emu.h"
|
||||
|
||||
#include "machine/eispc_kb.h"
|
||||
|
||||
// Devices
|
||||
#include "cpu/i86/i86.h"
|
||||
#include "machine/am9517a.h"
|
||||
#include "machine/i8251.h"
|
||||
#include "machine/i8255.h"
|
||||
#include "machine/pit8253.h"
|
||||
#include "machine/pic8259.h"
|
||||
#include "machine/upd765.h"
|
||||
#include "machine/ins8250.h"
|
||||
|
||||
// Expansion cards
|
||||
//#include "bus/isa/isa.h"
|
||||
//#include "bus/isa/isa_cards.h"
|
||||
#include "bus/isa/ega.h"
|
||||
#include "bus/isa/mda.h"
|
||||
#include "machine/pc_lpt.h"
|
||||
|
||||
#include "machine/ram.h"
|
||||
#include "machine/timer.h"
|
||||
#include "sound/spkrdev.h"
|
||||
#include "speaker.h"
|
||||
#include "imagedev/floppy.h"
|
||||
#include "formats/imd_dsk.h"
|
||||
#include "formats/pc_dsk.h"
|
||||
#include "bus/rs232/rs232.h"
|
||||
|
||||
#define LOG_PPI (1U << 1)
|
||||
#define LOG_PIT (1U << 2)
|
||||
#define LOG_PIC (1U << 3)
|
||||
#define LOG_KBD (1U << 4)
|
||||
#define LOG_DMA (1U << 5)
|
||||
#define LOG_IRQ (1U << 6)
|
||||
#define LOG_FDC (1U << 7)
|
||||
#define LOG_LPT (1U << 8)
|
||||
#define LOG_NMI (1U << 9)
|
||||
#define LOG_BITS (1U << 10)
|
||||
|
||||
//#define VERBOSE (LOG_BITS|LOG_KBD|LOG_IRQ)
|
||||
//#define LOG_OUTPUT_STREAM std::cout
|
||||
|
||||
#include "logmacro.h"
|
||||
|
||||
#define LOGPPI(...) LOGMASKED(LOG_PPI, __VA_ARGS__)
|
||||
#define LOGPIT(...) LOGMASKED(LOG_PIT, __VA_ARGS__)
|
||||
#define LOGPIC(...) LOGMASKED(LOG_PIC, __VA_ARGS__)
|
||||
#define LOGKBD(...) LOGMASKED(LOG_KBD, __VA_ARGS__)
|
||||
#define LOGDMA(...) LOGMASKED(LOG_DMA, __VA_ARGS__)
|
||||
#define LOGIRQ(...) LOGMASKED(LOG_IRQ, __VA_ARGS__)
|
||||
#define LOGFDC(...) LOGMASKED(LOG_FDC, __VA_ARGS__)
|
||||
#define LOGLPT(...) LOGMASKED(LOG_LPT, __VA_ARGS__)
|
||||
#define LOGNMI(...) LOGMASKED(LOG_NMI, __VA_ARGS__)
|
||||
#define LOGBITS(...) LOGMASKED(LOG_BITS, __VA_ARGS__)
|
||||
|
||||
class epc_state : public driver_device
|
||||
{
|
||||
public:
|
||||
epc_state(const machine_config &mconfig, device_type type, const char *tag) :
|
||||
driver_device(mconfig, type, tag)
|
||||
, m_maincpu(*this, "maincpu")
|
||||
, m_ram(*this, RAM_TAG)
|
||||
, m_isabus(*this, "isabus")
|
||||
, m_dma8237a(*this, "dma8237")
|
||||
, m_ppi8255(*this, "ppi8255")
|
||||
, m_io_dsw(*this, "DSW")
|
||||
, m_io_j10(*this, "J10")
|
||||
, m_lpt(*this, "lpt")
|
||||
, m_kbd8251(*this, "kbd8251")
|
||||
, m_keyboard(*this, "keyboard")
|
||||
, m_pic8259(*this, "pic8259")
|
||||
, m_pit8253(*this, "pit8253")
|
||||
, m_speaker(*this, "speaker")
|
||||
, m_fdc(*this, "fdc")
|
||||
, m_floppy_connectors(*this, "fdc:%u", 0)
|
||||
, m_uart(*this, "uart8250")
|
||||
{ }
|
||||
|
||||
void epc(machine_config &config);
|
||||
void init_epc();
|
||||
|
||||
|
||||
protected:
|
||||
virtual void machine_start() override;
|
||||
virtual void machine_reset() override;
|
||||
|
||||
private:
|
||||
required_device<i8086_cpu_device> m_maincpu;
|
||||
required_device<ram_device> m_ram;
|
||||
required_device<isa8_device> m_isabus;
|
||||
|
||||
// DMA
|
||||
DECLARE_WRITE_LINE_MEMBER(dma_tc_w);
|
||||
DECLARE_WRITE_LINE_MEMBER(dreq0_ck_w);
|
||||
DECLARE_WRITE_LINE_MEMBER( epc_dma_hrq_changed );
|
||||
DECLARE_WRITE_LINE_MEMBER( epc_dma8237_out_eop );
|
||||
DECLARE_READ8_MEMBER( epc_dma_read_byte );
|
||||
DECLARE_WRITE8_MEMBER( epc_dma_write_byte );
|
||||
template <int Channel> uint8_t epc_dma8237_io_r(offs_t offset);
|
||||
template <int Channel> void epc_dma8237_io_w(offs_t offset, uint8_t data);
|
||||
template <int Channel> DECLARE_WRITE_LINE_MEMBER(epc_dack_w);
|
||||
required_device<am9517a_device> m_dma8237a;
|
||||
uint8_t m_dma_segment[4];
|
||||
uint8_t m_dma_active;
|
||||
bool m_tc;
|
||||
bool m_txd;
|
||||
bool m_rxrdy;
|
||||
bool m_int;
|
||||
bool m_dreq0_ck;
|
||||
|
||||
// PPI
|
||||
required_device<i8255_device> m_ppi8255;
|
||||
DECLARE_WRITE8_MEMBER(ppi_portb_w);
|
||||
DECLARE_READ8_MEMBER(ppi_portc_r);
|
||||
uint8_t m_ppi_portb;
|
||||
required_ioport m_io_dsw;
|
||||
required_ioport m_io_j10;
|
||||
|
||||
// Printer port
|
||||
optional_device<pc_lpt_device> m_lpt;
|
||||
|
||||
// Keyboard Controller/USART
|
||||
required_device<i8251_device> m_kbd8251;
|
||||
required_device<eispc_keyboard_device> m_keyboard;
|
||||
emu_timer *m_kbdclk_timer;
|
||||
TIMER_CALLBACK_MEMBER(rxtxclk_w);
|
||||
int m_rxtx_clk_state;
|
||||
|
||||
// Interrupt Controller
|
||||
required_device<pic8259_device> m_pic8259;
|
||||
DECLARE_WRITE_LINE_MEMBER(int_w);
|
||||
uint8_t m_nmi_enabled;
|
||||
uint8_t m_8087_int = 0;
|
||||
const uint8_t m_parer_int = 0;
|
||||
const uint8_t m_iochck_int = 0;
|
||||
void update_nmi();
|
||||
|
||||
// Timer
|
||||
required_device<pit8253_device> m_pit8253;
|
||||
|
||||
// Speaker
|
||||
DECLARE_WRITE_LINE_MEMBER(speaker_ck_w);
|
||||
required_device<speaker_sound_device> m_speaker;
|
||||
|
||||
void epc_map(address_map &map);
|
||||
void epc_io(address_map &map);
|
||||
|
||||
// FDC
|
||||
void check_fdc_irq();
|
||||
void check_fdc_drq();
|
||||
required_device<i8272a_device> m_fdc;
|
||||
uint8_t m_ocr;
|
||||
bool m_irq; // System signal after glue logic
|
||||
bool m_drq; // System signal after glue logic
|
||||
bool m_fdc_irq; // FDC output pin
|
||||
bool m_fdc_drq; // FDC output pin
|
||||
|
||||
optional_device_array<floppy_connector, 4> m_floppy_connectors;
|
||||
DECLARE_FLOPPY_FORMATS( epc_floppy_formats );
|
||||
|
||||
// UART
|
||||
required_device<ins8250_device> m_uart;
|
||||
};
|
||||
|
||||
void epc_state::check_fdc_irq()
|
||||
{
|
||||
bool pirq = m_irq;
|
||||
m_irq = m_fdc_irq && (m_ocr & 4) && (m_ocr & 8); // IRQ enabled and not in reset?
|
||||
if(m_irq != pirq) // has the state changed?
|
||||
{
|
||||
LOGIRQ("FDC: IRQ6 request: %d\n", m_irq);
|
||||
m_pic8259->ir6_w(m_irq);
|
||||
}
|
||||
}
|
||||
|
||||
void epc_state::check_fdc_drq()
|
||||
{
|
||||
bool pdrq = m_drq;
|
||||
m_drq = m_fdc_drq && (m_ocr & 4) && (m_ocr & 8); // DREQ enabled and not in reset?
|
||||
if(m_drq != pdrq) // has the state changed?
|
||||
{
|
||||
LOGDMA("FDC: DMA channel 2 request: %d\n", m_drq);
|
||||
m_dma8237a->dreq2_w(m_drq);
|
||||
}
|
||||
}
|
||||
|
||||
void epc_state::epc_map(address_map &map)
|
||||
{
|
||||
map.unmap_value_high();
|
||||
map(0x20000, 0x9ffff).noprw(); // Base RAM - mapped to avoid unmaped errors when BIOS is probing RAM size
|
||||
// 0xa0000-0xaffff is reserved
|
||||
map(0xb0000, 0xb7fff).noprw(); // Monochrome RAM - mapped to avoid unaped errors when BIOS is probing RAM size
|
||||
map(0xb0000, 0xb7fff).noprw(); // Monochrome RAM - mapped to avoid unaped errors when BIOS is probing RAM size
|
||||
map(0xb8000, 0xbffff).noprw(); // Color/Graphics RAM - mapped to avoid unaped errors when BIOS is probing RAM size
|
||||
map(0xc0000, 0xeffff).noprw(); // Expansion ROM area - Hard Disk BIOS etc
|
||||
map(0xf0000, 0xfffff).rom().region("bios", 0);
|
||||
}
|
||||
|
||||
void epc_state::epc_io(address_map &map)
|
||||
{
|
||||
map(0x0000, 0x000f).mirror(0x10).lrw8("dma8237_rw",
|
||||
[this](offs_t offset) -> uint8_t
|
||||
{
|
||||
uint8_t data = m_dma8237a->read(offset);
|
||||
LOGDMA("dma8237_r %04x\n", offset);
|
||||
return data;
|
||||
},
|
||||
[this](offs_t offset, uint8_t data)
|
||||
{
|
||||
LOGDMA("dma8237_w %04x: %02x\n", offset, data);
|
||||
m_dma8237a->write(offset, data);
|
||||
}
|
||||
);
|
||||
|
||||
map(0x0020, 0x0021).mirror(0x1e).lrw8("pic8259_rw",
|
||||
[this](offs_t offset) -> uint8_t
|
||||
{
|
||||
uint8_t data = m_pic8259->read(offset);
|
||||
LOGPIC("pic8259_r %04x: %02x\n", offset, data);
|
||||
return data;
|
||||
},
|
||||
[this](offs_t offset, uint8_t data)
|
||||
{
|
||||
LOGPIC("pic8259_w %04x: %02x\n", offset, data);
|
||||
m_pic8259->write(offset, data);
|
||||
}
|
||||
);
|
||||
|
||||
map(0x0040, 0x0043).mirror(0x1c).lrw8("pit8253_rw",
|
||||
[this](offs_t offset) -> uint8_t
|
||||
{
|
||||
uint8_t data = m_pit8253->read(offset);
|
||||
LOGPIT("pit8253_r %04x\n", offset);
|
||||
return data;
|
||||
},
|
||||
[this](offs_t offset, uint8_t data)
|
||||
{
|
||||
LOGPIT("pit8253_w %04x: %02x\n", offset, data);
|
||||
m_pit8253->write(offset, data);
|
||||
}
|
||||
);
|
||||
|
||||
map(0x0060, 0x0060).mirror(0x1c).lrw8("kbd_8251_data_rw",
|
||||
[this]() -> uint8_t
|
||||
{
|
||||
uint8_t data = m_kbd8251->data_r();
|
||||
LOGKBD("kbd8251_r %02x\n", data);
|
||||
return data;
|
||||
},
|
||||
[this](offs_t offset, uint8_t data)
|
||||
{
|
||||
LOGKBD("kbd8251_w 0x60 %02x\n", data);
|
||||
m_kbd8251->data_w(data);
|
||||
}
|
||||
);
|
||||
// NOTE: PPI Port A is not mapped
|
||||
map(0x0061, 0x0061).mirror(0x1c).lrw8("ppi8255_rw", // PPI Port B
|
||||
[this](offs_t offset) -> uint8_t
|
||||
{
|
||||
uint8_t data = m_ppi8255->read(1);
|
||||
LOGPPI("ppi8255_r Port B: %02x\n", data);
|
||||
return data;
|
||||
},
|
||||
[this](offs_t offset, uint8_t data)
|
||||
{
|
||||
LOGPPI("ppi8255_w Port B: %02x\n", data);
|
||||
m_ppi8255->write(1, data);
|
||||
}
|
||||
);
|
||||
|
||||
map(0x0062, 0x0062).mirror(0x1c).lrw8("ppi8255_rw", // PPI Port C
|
||||
[this](offs_t offset) -> uint8_t
|
||||
{
|
||||
uint8_t data = m_ppi8255->read(2);
|
||||
LOGPPI("ppi8255_r Port C: %02x\n", data);
|
||||
return data;
|
||||
},
|
||||
[this](offs_t offset, uint8_t data)
|
||||
{
|
||||
LOGPPI("ppi8255_w Port C: %02x\n", data);
|
||||
m_ppi8255->write(2, data);
|
||||
}
|
||||
);
|
||||
|
||||
map(0x0063, 0x0063).lrw8("ppi8255_rw", // PPI Control register
|
||||
[this](offs_t offset) -> uint8_t
|
||||
{
|
||||
uint8_t data = m_ppi8255->read(3);
|
||||
LOGPPI("ppi8255_r Control: %02x\n", data);
|
||||
return data;
|
||||
},
|
||||
[this](offs_t offset, uint8_t data)
|
||||
{
|
||||
LOGPPI("ppi8255_w Control: %02x\n", data);
|
||||
m_ppi8255->write(3, data);
|
||||
}
|
||||
);
|
||||
|
||||
map(0x0070, 0x0070).mirror(0x0e).lw8("i8251_data_w",
|
||||
[this](offs_t offset, uint8_t data)
|
||||
{
|
||||
LOGKBD("kbd8251_w 0x70: %02x\n", data);
|
||||
m_kbd8251->data_w(data);
|
||||
}
|
||||
);
|
||||
|
||||
map(0x0071, 0x0071).mirror(0x0e).lrw8("kbd_8251_stat_ctrl_rw",
|
||||
[this](offs_t offset) -> uint8_t
|
||||
{
|
||||
uint8_t stat = m_kbd8251->status_r();
|
||||
//LOGKBD("kbd8251_status_r %02x\n", stat);
|
||||
return stat;
|
||||
},
|
||||
[this](offs_t offset, uint8_t data)
|
||||
{
|
||||
LOGKBD("kbd8251_control_w 0x71: %02x\n", data);
|
||||
m_kbd8251->control_w(data);
|
||||
}
|
||||
);
|
||||
|
||||
map(0x0080, 0x0083).mirror(0xc).lw8("dma_segement_w",
|
||||
[this](offs_t offset, uint8_t data)
|
||||
{
|
||||
LOGDMA("dma_segment_w %04x: %02x\n", offset, data);
|
||||
m_dma_segment[offset] = data & 0x0f;
|
||||
}
|
||||
);
|
||||
|
||||
map(0x00a0, 0x00a1).mirror(0xe).lw8("nmi_enable_w",
|
||||
[this](offs_t offset, uint8_t data)
|
||||
{
|
||||
LOGNMI("nmi_enable_w %04x: %02x\n", offset, data);
|
||||
m_nmi_enabled = BIT(data,7);
|
||||
update_nmi();
|
||||
}
|
||||
);
|
||||
|
||||
// FDC Output Control Register (same as PC XT DOR)
|
||||
map(0x03f2, 0x03f3).lw8("ocr_w", // B0-B1 Drive select 0-3
|
||||
[this](offs_t offset, uint8_t data) // B2 FDC Reset line
|
||||
{ // B3 Enable FDC DMA/IRQ
|
||||
LOGFDC("FDC OCR: %02x\n", data);// B4-B7 Motor on for selected drive
|
||||
uint8_t pocr = m_ocr;
|
||||
uint8_t fid = m_ocr & 3;
|
||||
m_ocr = data;
|
||||
if ((m_ocr & 4) && m_floppy_connectors[fid]) // Not in reset and there is a floppy drive attached
|
||||
{
|
||||
floppy_image_device *floppy = m_floppy_connectors[fid]->get_device(); // try to retrieve the floppy
|
||||
if (floppy)
|
||||
{
|
||||
LOGFDC(" - Motor %s for drive %d\n", (m_ocr & (0x10 << fid)) ? "ON" : "OFF", fid);
|
||||
floppy->mon_w(!(m_ocr & (0x10 << fid)));
|
||||
LOGFDC(" - Setting a floppy for drive %d\n", fid);
|
||||
m_fdc->set_floppy((m_ocr & (0x10 << fid)) ? floppy : nullptr);
|
||||
}
|
||||
}
|
||||
if (((pocr ^ m_ocr) & 4) && (m_ocr & 4) == 0) // If FDC reset state bit has changed to low then reset the FDC
|
||||
m_fdc->reset();
|
||||
check_fdc_irq();
|
||||
check_fdc_drq();
|
||||
}
|
||||
);
|
||||
|
||||
map(0x03f4, 0x03f5).m(m_fdc, FUNC(i8272a_device::map));
|
||||
|
||||
map(0x03bc, 0x03be).lrw8("lpt_rw",
|
||||
[this](address_space &space, offs_t offset, uint8_t mem_mask) -> uint8_t
|
||||
{
|
||||
uint8_t data = m_lpt->read(space, offset);
|
||||
LOGLPT("LPT read offset %02x: %02x\n", offset, data);
|
||||
return data;
|
||||
},
|
||||
[this](address_space &space, offs_t offset, uint8_t data)
|
||||
{
|
||||
LOGLPT("LPT write offset %02x: %02x\n", offset, data);
|
||||
m_lpt->write(space, offset, data);
|
||||
}
|
||||
);
|
||||
|
||||
map(0x03f8, 0x03ff).rw(m_uart, FUNC(ins8250_device::ins8250_r), FUNC(ins8250_device::ins8250_w));
|
||||
}
|
||||
|
||||
void epc_state::machine_start()
|
||||
{
|
||||
m_maincpu->space(AS_PROGRAM).install_ram(0, m_ram->size() - 1, m_ram->pointer());
|
||||
|
||||
std::fill_n(&m_dma_segment[0], 4, 0);
|
||||
m_dma_active = 0;
|
||||
m_tc = false;
|
||||
m_int = 1;
|
||||
m_txd = false;
|
||||
m_rxrdy = false;
|
||||
m_dreq0_ck = true;
|
||||
m_rxtx_clk_state = 0;
|
||||
|
||||
save_item(NAME(m_dma_segment));
|
||||
save_item(NAME(m_dma_active));
|
||||
save_item(NAME(m_tc));
|
||||
save_item(NAME(m_int));
|
||||
save_item(NAME(m_txd));
|
||||
save_item(NAME(m_rxrdy));
|
||||
save_item(NAME(m_ocr));
|
||||
m_ocr = 0x00;
|
||||
save_item(NAME(m_ppi_portb));
|
||||
save_item(NAME(m_dreq0_ck));
|
||||
save_item(NAME(m_rxtx_clk_state));
|
||||
}
|
||||
|
||||
void epc_state::machine_reset()
|
||||
{
|
||||
m_ppi_portb = 0;
|
||||
m_keyboard->rst_line_w(ASSERT_LINE);
|
||||
m_nmi_enabled = 0;
|
||||
m_kbd8251->write_cts(0); // Held low always
|
||||
}
|
||||
|
||||
void epc_state::init_epc()
|
||||
{
|
||||
/* Keyboard UART Rxc/Txc is 19.2 kHz from x96 divider */
|
||||
m_kbdclk_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(epc_state::rxtxclk_w), this));
|
||||
m_kbdclk_timer->adjust(attotime::from_hz((XTAL(18'432'000) / 96) / 5));
|
||||
}
|
||||
|
||||
TIMER_CALLBACK_MEMBER(epc_state::rxtxclk_w)
|
||||
{
|
||||
m_kbd8251->write_rxc(m_rxtx_clk_state);
|
||||
m_kbd8251->write_txc(m_rxtx_clk_state);
|
||||
m_rxtx_clk_state ^= 0x01;
|
||||
m_kbdclk_timer->adjust(attotime::from_hz((XTAL(18'432'000) / 96) / 5));
|
||||
}
|
||||
|
||||
|
||||
template <int Channel>
|
||||
uint8_t epc_state::epc_dma8237_io_r(offs_t offset)
|
||||
{
|
||||
LOGDMA("epc_dma8237_io_r: %d\n", Channel);
|
||||
if (Channel == 2)
|
||||
return m_fdc->dma_r();
|
||||
else
|
||||
return m_isabus->dack_r(Channel);
|
||||
}
|
||||
|
||||
template <int Channel>
|
||||
void epc_state::epc_dma8237_io_w(offs_t offset, uint8_t data)
|
||||
{
|
||||
LOGDMA("epc_dma8237_io_w: %d - %02x\n", Channel, data);
|
||||
if (Channel == 2)
|
||||
m_fdc->dma_w(data);
|
||||
else
|
||||
m_isabus->dack_w(Channel, data);
|
||||
}
|
||||
|
||||
template <int Channel>
|
||||
WRITE_LINE_MEMBER(epc_state::epc_dack_w)
|
||||
{
|
||||
LOGDMA("epc_dack_w: %d - %d\n", Channel, state);
|
||||
|
||||
m_isabus->dack_line_w(Channel, state);
|
||||
|
||||
if (!state)
|
||||
{
|
||||
m_dma_active |= 1 << Channel;
|
||||
if (Channel == 0)
|
||||
m_dma8237a->dreq0_w(0);
|
||||
if (m_tc)
|
||||
m_isabus->eop_w(Channel, ASSERT_LINE);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_dma_active &= ~(1 << Channel);
|
||||
if (m_tc)
|
||||
m_isabus->eop_w(Channel, CLEAR_LINE);
|
||||
}
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER(epc_state::dma_tc_w)
|
||||
{
|
||||
m_tc = (state == ASSERT_LINE);
|
||||
for (int channel = 0; channel < 4; channel++)
|
||||
{
|
||||
if (BIT(m_dma_active, channel))
|
||||
{
|
||||
LOGDMA("dma_tc_w ch %d: %d\n", channel, state);
|
||||
m_isabus->eop_w(channel, state);
|
||||
}
|
||||
}
|
||||
|
||||
// Special treatment for on board FDC
|
||||
if (BIT(m_dma_active, 2))
|
||||
{
|
||||
m_fdc->tc_w(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_fdc->tc_w(1);
|
||||
}
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER(epc_state::dreq0_ck_w)
|
||||
{
|
||||
if (state && !m_dreq0_ck && !BIT(m_dma_active, 0))
|
||||
m_dma8237a->dreq0_w(1);
|
||||
|
||||
m_dreq0_ck = state;
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER(epc_state::speaker_ck_w)
|
||||
{
|
||||
m_speaker->level_w((m_ppi_portb & 0x02) && state ? 1 : 0);
|
||||
}
|
||||
|
||||
/**********************************************************
|
||||
*
|
||||
* PPI8255 interface
|
||||
*
|
||||
*
|
||||
* PORT A (not used)
|
||||
*
|
||||
* Reads of port A is shadowed by UART8251A's read register
|
||||
* gaining some compatibility with PC software. The UART8251
|
||||
* communicates with the serial keyboard and extends it with
|
||||
* write capability enabling keyboard led control as with a
|
||||
* PC AT keyboard.
|
||||
*
|
||||
* PORT B (output)
|
||||
* 0 - PB0 - - Control signal for the sound generator (short beeps)
|
||||
* 1 - PB1 - - Control signal for the sound generator
|
||||
* 2 - PB2 - - Unused
|
||||
* 3 - PB3 - - Data select for the configuration switches 0=SW1-4 1=SW5-8
|
||||
* 4 - PB4 - * - Enable ram parity check
|
||||
* 5 - PB5 - * - Enable expansion I/O check
|
||||
* 6 - PB6 - * - Keyboard reset
|
||||
* 7 - PB7 - - Reset keyboard interrupt
|
||||
*
|
||||
* PORT C
|
||||
* 0 - PC0 - - Dipswitch SW 1/5 PB3=0/PB3=1
|
||||
* 1 - PC1 - - Dipswitch SW 2/6 PB3=0/PB3=1
|
||||
* 2 - PC2 - - Dipswitch SW 3/7 PB3=0/PB3=1
|
||||
* 3 - PC3 - - Dipswitch SW 4/8 PB3=0/PB3=1
|
||||
* 4 - PC4 - SPK - Speaker/cassette data (spare in PC XT spec)
|
||||
* 5 - PC5 - OUT2 - OUT2 from 8253 (ibmpcjr compatible)
|
||||
* 6 - PC6 -
|
||||
* 7 - PC7 -
|
||||
*
|
||||
* Ericsson PC SW:
|
||||
* 1 - Not used. Must be set to OFF
|
||||
* 2 - OFF - 8087 present
|
||||
* ON - No 8087 present *)
|
||||
* 3 - Not Used. Don't care but OFF *)
|
||||
* 4 - Not Used. Must be set to ON
|
||||
* 5+6 - Used to select display
|
||||
* OFF OFF - Monochrome HR graphics monitor 3111 installed + 1020 color secondary monitor
|
||||
* ON OFF - Monochrome HR graphics monitor 3111 installed + optional 1020 color main monitor *)
|
||||
* OFF ON - Not used
|
||||
* ON ON - Not used
|
||||
* 7+8 - Used to select number of disk drives
|
||||
* OFF OFF - Not used
|
||||
* ON OFF - Not used
|
||||
* OFF ON - two disk drives, system units 1030-1 and 1030-2
|
||||
* ON ON - one disk drive, system units 1030-3, 1030-4, 1031-1 and 1031-2
|
||||
*
|
||||
* *) - Factory settings
|
||||
*
|
||||
**********************************************************/
|
||||
|
||||
READ8_MEMBER( epc_state::ppi_portc_r )
|
||||
{
|
||||
uint8_t data;
|
||||
|
||||
// Read 4 configurations dip switches depending on PB3
|
||||
data = (m_io_dsw->read() >> ((m_ppi_portb & 0x08) ? 4 : 0) & 0x0f);
|
||||
|
||||
// TODO: verify what PC4-PC7 is used for, if anything
|
||||
|
||||
LOGPPI("PPI Port C read: %02x\n", data);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
WRITE8_MEMBER( epc_state::ppi_portb_w )
|
||||
{
|
||||
LOGPPI("PPI Port B write: %02x\n", data);
|
||||
LOGPPI(" PB0 - Enable beeper : %d\n", (data & 0x01) ? 1 : 0);
|
||||
LOGPPI(" PB1 - Beeper data : %d\n", (data & 0x02) ? 1 : 0);
|
||||
LOGPPI(" PB2 - Unused : %d\n", (data & 0x04) ? 1 : 0);
|
||||
LOGPPI(" PB3 - Port C dip switch select : %d\n", (data & 0x08) ? 1 : 0);
|
||||
LOGPPI(" PB4 - RAM parity enable : %d\n", (data & 0x10) ? 1 : 0);
|
||||
LOGPPI(" PB5 - ISA error checking enable : %d\n", (data & 0x20) ? 1 : 0);
|
||||
LOGPPI(" PB6 - Reset keyboard : %d\n", (data & 0x40) ? 1 : 0);
|
||||
LOGPPI(" PB7 - Reset keyboard interrupt : %d\n", (data & 0x80) ? 1 : 0);
|
||||
|
||||
uint8_t changed = m_ppi_portb ^ data;
|
||||
|
||||
m_ppi_portb = data;
|
||||
|
||||
if (changed & 0x40)
|
||||
{
|
||||
if (m_ppi_portb & 0x40)
|
||||
{
|
||||
LOGKBD("PB6 set, clearing Keyboard RESET\n");
|
||||
m_keyboard->rst_line_w(CLEAR_LINE);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGKBD("PB6 cleared, asserting Keyboard RESET\n");
|
||||
m_keyboard->rst_line_w(ASSERT_LINE);
|
||||
}
|
||||
}
|
||||
|
||||
if (changed & m_ppi_portb & 0x80)
|
||||
{
|
||||
LOGIRQ("PB7 set, clearing IRQ1 and releasing HOLD\n");
|
||||
m_pic8259->ir1_w(CLEAR_LINE);
|
||||
m_keyboard->hold_w(ASSERT_LINE);
|
||||
}
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER(epc_state::int_w)
|
||||
{
|
||||
if (m_int != state)
|
||||
{
|
||||
LOGIRQ("int_w: %d\n", state);
|
||||
m_int = state;
|
||||
m_maincpu->set_input_line(0, m_int);
|
||||
}
|
||||
}
|
||||
|
||||
static void epc_isa8_cards(device_slot_interface &device)
|
||||
{
|
||||
device.option_add("epc_mda", ISA8_EPC_MDA);
|
||||
device.option_add("ega", ISA8_EGA);
|
||||
// device.option_add("epc_hdc1065", ISA8_EPC_HDC1065);
|
||||
// device.option_add("epc_mb1080", ISA8_EPC_MB1080);
|
||||
}
|
||||
|
||||
FLOPPY_FORMATS_MEMBER( epc_state::epc_floppy_formats )
|
||||
FLOPPY_PC_FORMAT,
|
||||
FLOPPY_IMD_FORMAT
|
||||
FLOPPY_FORMATS_END
|
||||
|
||||
static void epc_sd_floppies(device_slot_interface &device)
|
||||
{
|
||||
device.option_add("525sd", FLOPPY_525_SD);
|
||||
}
|
||||
|
||||
void epc_state::epc(machine_config &config)
|
||||
{
|
||||
I8088(config, m_maincpu, XTAL(14'318'181) / 3.0); // TWE crystal marked X1 verified divided through a 82874
|
||||
m_maincpu->set_addrmap(AS_PROGRAM, &epc_state::epc_map);
|
||||
m_maincpu->set_addrmap(AS_IO, &epc_state::epc_io);
|
||||
m_maincpu->set_irq_acknowledge_callback("pic8259", FUNC(pic8259_device::inta_cb));
|
||||
|
||||
// DMA
|
||||
AM9517A(config, m_dma8237a, XTAL(14'318'181) / 3.0); // TWE crystal marked X1 verified
|
||||
m_dma8237a->out_hreq_callback().set(FUNC(epc_state::epc_dma_hrq_changed));
|
||||
m_dma8237a->out_eop_callback().set(FUNC(epc_state::dma_tc_w));
|
||||
m_dma8237a->in_memr_callback().set(FUNC(epc_state::epc_dma_read_byte));
|
||||
m_dma8237a->out_memw_callback().set(FUNC(epc_state::epc_dma_write_byte));
|
||||
m_dma8237a->in_ior_callback<1>().set(FUNC(epc_state::epc_dma8237_io_r<1>));
|
||||
m_dma8237a->in_ior_callback<2>().set(FUNC(epc_state::epc_dma8237_io_r<2>));
|
||||
m_dma8237a->in_ior_callback<3>().set(FUNC(epc_state::epc_dma8237_io_r<3>));
|
||||
m_dma8237a->out_iow_callback<0>().set(FUNC(epc_state::epc_dma8237_io_w<0>));
|
||||
m_dma8237a->out_iow_callback<1>().set(FUNC(epc_state::epc_dma8237_io_w<1>));
|
||||
m_dma8237a->out_iow_callback<2>().set(FUNC(epc_state::epc_dma8237_io_w<2>));
|
||||
m_dma8237a->out_iow_callback<3>().set(FUNC(epc_state::epc_dma8237_io_w<3>));
|
||||
m_dma8237a->out_dack_callback<0>().set(FUNC(epc_state::epc_dack_w<0>));
|
||||
m_dma8237a->out_dack_callback<1>().set(FUNC(epc_state::epc_dack_w<1>));
|
||||
m_dma8237a->out_dack_callback<2>().set(FUNC(epc_state::epc_dack_w<2>));
|
||||
m_dma8237a->out_dack_callback<3>().set(FUNC(epc_state::epc_dack_w<3>));
|
||||
|
||||
// TTL-level serial keyboard callback
|
||||
EISPC_KB(config, "keyboard").txd_cb().set([this](bool state)
|
||||
{
|
||||
LOGBITS("KBD->EPC: %d\n", state);
|
||||
m_kbd8251->write_rxd(state);
|
||||
});
|
||||
|
||||
// Keyboard USART
|
||||
I8251( config, m_kbd8251, XTAL(14'318'181) / 6.0 ); // TWE crystal marked X1 verified divided through a 82874
|
||||
|
||||
m_kbd8251->txd_handler().set([this](bool state)
|
||||
{
|
||||
if (m_txd != state)
|
||||
{
|
||||
LOGBITS("EPC->KBD: %d\n", state);
|
||||
m_txd = state;
|
||||
m_keyboard->rxd_w(m_txd);
|
||||
}
|
||||
});
|
||||
|
||||
m_kbd8251->rxrdy_handler().set([this](bool state)
|
||||
{
|
||||
m_rxrdy = state;
|
||||
LOGKBD("KBD RxRdy: %d HOLD: %d\n", m_rxrdy ? 1 : 0, m_rxrdy ? 0 : 1);
|
||||
m_keyboard->hold_w(!m_rxrdy);
|
||||
if (m_rxrdy)
|
||||
{
|
||||
LOGIRQ("RxRdy set, asserting IRQ1\n");
|
||||
m_pic8259->ir1_w(ASSERT_LINE); // Cleared by setting PB7
|
||||
}
|
||||
});
|
||||
m_kbd8251->dtr_handler().set([this](bool state) // Controls RCLK for INS8250, either 19.2KHz or INS8250 BAUDOUT
|
||||
{
|
||||
LOGKBD("KBD DTR: %d\n", state ? 1 : 0); // TODO: Implement clock selection mux, need to check what state does what
|
||||
});
|
||||
|
||||
// Interrupt Controller
|
||||
PIC8259(config, m_pic8259);
|
||||
m_pic8259->out_int_callback().set(FUNC(epc_state::int_w));
|
||||
|
||||
// Parallel port
|
||||
I8255A(config, m_ppi8255);
|
||||
m_ppi8255->out_pa_callback().set([this] (uint8_t data) { LOGPPI("PPI: write %02x to unused Port A\n", data); } ); // Port A is not used
|
||||
m_ppi8255->out_pb_callback().set(FUNC(epc_state::ppi_portb_w));
|
||||
m_ppi8255->in_pc_callback().set(FUNC(epc_state::ppi_portc_r));
|
||||
|
||||
// system board Parallel port
|
||||
PC_LPT(config, m_lpt);
|
||||
m_lpt->irq_handler().set([this](int state)
|
||||
{ // Jumper field J10 decides what IRQ to pull
|
||||
if ((m_io_j10->read() & 0x03) == 0x01) { LOGIRQ("LPT IRQ2: %d\n", state); m_pic8259->ir2_w(state); }
|
||||
if ((m_io_j10->read() & 0x0c) == 0x04) { LOGIRQ("LPT IRQ3: %d\n", state); m_pic8259->ir3_w(state); }
|
||||
if ((m_io_j10->read() & 0x30) == 0x10) { LOGIRQ("LPT IRQ4: %d\n", state); m_pic8259->ir4_w(state); }
|
||||
if ((m_io_j10->read() & 0xc0) == 0x40) { LOGIRQ("LPT IRQ7: %d\n", state); m_pic8259->ir7_w(state); } // Factory setting
|
||||
});
|
||||
|
||||
// Timer
|
||||
PIT8253(config, m_pit8253);
|
||||
m_pit8253->set_clk<0>((XTAL(14'318'181) / 3.0) / 2.0 );
|
||||
m_pit8253->set_clk<1>((XTAL(14'318'181) / 3.0) / 2.0 );
|
||||
m_pit8253->set_clk<2>((XTAL(14'318'181) / 3.0) / 2.0 );
|
||||
m_pit8253->out_handler<0>().set(m_pic8259, FUNC(pic8259_device::ir0_w));
|
||||
m_pit8253->out_handler<1>().set(FUNC(epc_state::dreq0_ck_w));
|
||||
m_pit8253->out_handler<2>().set(FUNC(epc_state::speaker_ck_w));
|
||||
|
||||
// Speaker
|
||||
SPEAKER(config, "mono").front_center();
|
||||
SPEAKER_SOUND(config, m_speaker).add_route(ALL_OUTPUTS, "mono", 1.00);
|
||||
|
||||
// ISA bus
|
||||
ISA8(config, m_isabus, XTAL(14'318'181) / 3.0); // TEW crystal marked X1 verified
|
||||
m_isabus->set_memspace(m_maincpu, AS_PROGRAM);
|
||||
m_isabus->set_iospace(m_maincpu, AS_IO);
|
||||
//m_isabus->irq2_callback().set(m_pic8259, FUNC(pic8259_device::ir2_w)); // Reserved in service manual
|
||||
m_isabus->irq3_callback().set(m_pic8259, FUNC(pic8259_device::ir3_w));
|
||||
m_isabus->irq4_callback().set(m_pic8259, FUNC(pic8259_device::ir4_w));
|
||||
m_isabus->irq5_callback().set(m_pic8259, FUNC(pic8259_device::ir5_w));
|
||||
m_isabus->irq6_callback().set(m_pic8259, FUNC(pic8259_device::ir6_w));
|
||||
m_isabus->irq7_callback().set(m_pic8259, FUNC(pic8259_device::ir7_w));
|
||||
m_isabus->drq1_callback().set(m_dma8237a, FUNC(am9517a_device::dreq1_w));
|
||||
m_isabus->drq2_callback().set(m_dma8237a, FUNC(am9517a_device::dreq2_w));
|
||||
m_isabus->drq3_callback().set(m_dma8237a, FUNC(am9517a_device::dreq3_w));
|
||||
//m_isabus->iochck_callback().set(FUNC(epc_state::chck_w)); // TODO: Check schematics
|
||||
m_isabus->iochck_callback().set([this] (int state)
|
||||
{
|
||||
if (m_nmi_enabled && !state && 0)
|
||||
{
|
||||
LOGNMI("IOCHCK: NMI Requested\n");
|
||||
update_nmi();
|
||||
}
|
||||
});
|
||||
|
||||
ISA8_SLOT(config, "isa1", 0, m_isabus, epc_isa8_cards, "epc_mda", false);
|
||||
ISA8_SLOT(config, "isa2", 0, m_isabus, epc_isa8_cards, nullptr, false);
|
||||
ISA8_SLOT(config, "isa3", 0, m_isabus, epc_isa8_cards, nullptr, false);
|
||||
ISA8_SLOT(config, "isa4", 0, m_isabus, epc_isa8_cards, nullptr, false);
|
||||
ISA8_SLOT(config, "isa5", 0, m_isabus, epc_isa8_cards, nullptr, false);
|
||||
ISA8_SLOT(config, "isa6", 0, m_isabus, epc_isa8_cards, nullptr, false);
|
||||
|
||||
// System board has 128kB memory with parity, expansion can be achieved through the
|
||||
// 128kB Memory Expansion Board 1090 and/or the 128kB Multifunction Board MB1080-001
|
||||
// and/or the 384kB MB1080-002. The MB1080 DRAM might need to be dynamically added as
|
||||
// base address and also a video memory hole is configuarable.
|
||||
RAM(config, m_ram).set_default_size("128K").set_extra_options("256K, 384K, 512K, 640K");
|
||||
|
||||
// FDC
|
||||
I8272A(config, m_fdc, XTAL(16'000'000) / 2, false); // TEW crystal marked X3 verified
|
||||
m_fdc->intrq_wr_callback().set([this] (int state){ m_fdc_irq = state; check_fdc_irq(); });
|
||||
m_fdc->drq_wr_callback().set([this] (int state){ m_fdc_drq = state; check_fdc_drq(); });
|
||||
FLOPPY_CONNECTOR(config, m_floppy_connectors[0], epc_sd_floppies, "525sd", epc_floppy_formats);
|
||||
FLOPPY_CONNECTOR(config, m_floppy_connectors[1], epc_sd_floppies, "525sd", epc_floppy_formats);
|
||||
//SOFTWARE_LIST(config, "epc_flop_list").set_original("epc_flop");
|
||||
|
||||
// system board UART
|
||||
INS8250(config, m_uart, XTAL(18'432'000) / 10); // TEW crystal marked X2 verified. TODO: Let 8051 DTR control RCLK (see above)
|
||||
m_uart->out_tx_callback().set("uart", FUNC(rs232_port_device::write_txd));
|
||||
m_uart->out_dtr_callback().set("uart", FUNC(rs232_port_device::write_dtr));
|
||||
m_uart->out_rts_callback().set("uart", FUNC(rs232_port_device::write_rts));
|
||||
m_uart->out_int_callback().set([this](int state)
|
||||
{ // Jumper field J10 decides what IRQ to pull
|
||||
if ((m_io_j10->read() & 0x03) == 0x02) { LOGIRQ("UART IRQ2: %d\n", state); m_pic8259->ir2_w(state); }
|
||||
if ((m_io_j10->read() & 0x0c) == 0x08) { LOGIRQ("UART IRQ3: %d\n", state); m_pic8259->ir3_w(state); }
|
||||
if ((m_io_j10->read() & 0x30) == 0x20) { LOGIRQ("UART IRQ4: %d\n", state); m_pic8259->ir4_w(state); } // Factory setting
|
||||
if ((m_io_j10->read() & 0xc0) == 0x80) { LOGIRQ("UART IRQ7: %d\n", state); m_pic8259->ir7_w(state); }
|
||||
});
|
||||
|
||||
rs232_port_device &rs232(RS232_PORT(config, "uart", default_rs232_devices, nullptr));
|
||||
rs232.rxd_handler().set(m_uart, FUNC(ins8250_uart_device::rx_w));
|
||||
rs232.dcd_handler().set(m_uart, FUNC(ins8250_uart_device::dcd_w));
|
||||
rs232.dsr_handler().set(m_uart, FUNC(ins8250_uart_device::dsr_w));
|
||||
rs232.ri_handler().set(m_uart, FUNC(ins8250_uart_device::ri_w));
|
||||
rs232.cts_handler().set(m_uart, FUNC(ins8250_uart_device::cts_w));
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
void epc_state::update_nmi()
|
||||
{
|
||||
if (m_nmi_enabled &&
|
||||
((m_8087_int && (m_io_dsw->read() & 0x02)) || // FPU int only if FPU is enabled by DSW2
|
||||
(m_parer_int != 0) || // Parity error is always false as it is an emulator, at least for now
|
||||
(m_iochck_int != 0))) // Same goes for ISA board errors
|
||||
{
|
||||
LOGNMI(" NMI asserted\n");
|
||||
m_maincpu->set_input_line(INPUT_LINE_NMI, ASSERT_LINE);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGNMI(" NMI Cleared\n");
|
||||
m_maincpu->set_input_line(INPUT_LINE_NMI, CLEAR_LINE);
|
||||
}
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER( epc_state::epc_dma_hrq_changed )
|
||||
{
|
||||
LOGDMA("epc_dma_hrq_changed %d\n", state);
|
||||
|
||||
m_maincpu->set_input_line(INPUT_LINE_HALT, state ? ASSERT_LINE : CLEAR_LINE);
|
||||
|
||||
/* Assert HLDA */
|
||||
m_dma8237a->hack_w(state);
|
||||
}
|
||||
|
||||
|
||||
READ8_MEMBER( epc_state::epc_dma_read_byte )
|
||||
{
|
||||
if ((m_dma_active & 0x0f) == 0)
|
||||
{
|
||||
LOGDMA("epc_dma_read_byte failed\n");
|
||||
return 0xff;
|
||||
}
|
||||
|
||||
const int seg = (BIT(m_dma_active, 2) ? 0 : 2) | (BIT(m_dma_active, 3) ? 0 : 1);
|
||||
return m_maincpu->space(AS_PROGRAM).read_byte(offset | u32(m_dma_segment[seg]) << 16);
|
||||
}
|
||||
|
||||
WRITE8_MEMBER( epc_state::epc_dma_write_byte )
|
||||
{
|
||||
if ((m_dma_active & 0x0f) == 0)
|
||||
{
|
||||
LOGDMA("epc_dma_write_byte failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
const int seg = (BIT(m_dma_active, 2) ? 0 : 2) | (BIT(m_dma_active, 3) ? 0 : 1);
|
||||
m_maincpu->space(AS_PROGRAM).write_byte(offset | u32(m_dma_segment[seg]) << 16, data);
|
||||
}
|
||||
|
||||
|
||||
static INPUT_PORTS_START( epc_ports )
|
||||
PORT_START("DSW")
|
||||
PORT_DIPNAME( 0x01, 0x01, "Not used")
|
||||
PORT_DIPSETTING( 0x00, "ON - Don't use")
|
||||
PORT_DIPSETTING( 0x01, "OFF - Factory Setting")
|
||||
PORT_DIPNAME( 0x02, 0x00, "8087 installed")
|
||||
PORT_DIPSETTING( 0x00, DEF_STR(No) )
|
||||
PORT_DIPSETTING( 0x02, DEF_STR(Yes) )
|
||||
PORT_DIPNAME( 0x04, 0x04, "Not used")
|
||||
PORT_DIPSETTING( 0x00, "ON - Don't care")
|
||||
PORT_DIPSETTING( 0x04, "OFF - Factory Setting")
|
||||
PORT_DIPNAME( 0x08, 0x00, "Not used")
|
||||
PORT_DIPSETTING( 0x00, "ON - Factory Setting")
|
||||
PORT_DIPSETTING( 0x08, "OFF - Don't use")
|
||||
PORT_DIPNAME( 0x30, 0x30, "Main monitor")
|
||||
PORT_DIPSETTING( 0x00, "Not used" )
|
||||
PORT_DIPSETTING( 0x10, "Optional 1020 color" )
|
||||
PORT_DIPSETTING( 0x20, "Not used" )
|
||||
PORT_DIPSETTING( 0x30, "3111 HR Monochrome" )
|
||||
PORT_DIPNAME( 0xc0, 0x40, "Number of floppy drives")
|
||||
PORT_DIPSETTING( 0x00, "1" )
|
||||
PORT_DIPSETTING( 0x40, "2" )
|
||||
PORT_DIPSETTING( 0x80, "Not used" )
|
||||
PORT_DIPSETTING( 0xc0, "Not used" )
|
||||
|
||||
PORT_START("J10") // Jumper area, field 0=no jumper 1=LPT 2=COM 3=n/a
|
||||
PORT_DIPNAME(0x03, 0x00, "IRQ2")
|
||||
PORT_DIPSETTING(0x00, "no jumper")
|
||||
PORT_DIPSETTING(0x01, "LPT")
|
||||
PORT_DIPSETTING(0x02, "COM")
|
||||
PORT_DIPNAME(0x0c, 0x00, "IRQ3")
|
||||
PORT_DIPSETTING(0x00, "no jumper")
|
||||
PORT_DIPSETTING(0x04, "LPT")
|
||||
PORT_DIPSETTING(0x08, "COM")
|
||||
PORT_DIPNAME(0x30, 0x20, "IRQ4")
|
||||
PORT_DIPSETTING(0x00, "no jumper")
|
||||
PORT_DIPSETTING(0x10, "LPT")
|
||||
PORT_DIPSETTING(0x20, "COM")
|
||||
PORT_DIPNAME(0xc0, 0x40, "IRQ7")
|
||||
PORT_DIPSETTING(0x00, "no jumper")
|
||||
PORT_DIPSETTING(0x40, "LPT")
|
||||
PORT_DIPSETTING(0x80, "COM")
|
||||
INPUT_PORTS_END
|
||||
|
||||
ROM_START( epc )
|
||||
ROM_REGION(0x10000,"bios", 0)
|
||||
ROM_DEFAULT_BIOS("p860110")
|
||||
ROM_SYSTEM_BIOS(0, "p840705", "P840705")
|
||||
ROMX_LOAD("ericsson_8088.bin", 0xe000, 0x2000, CRC(3953c38d) SHA1(2bfc1f1d11d0da5664c3114994fc7aa3d6dd010d), ROM_BIOS(0))
|
||||
ROM_SYSTEM_BIOS(1, "p860110", "P860110")
|
||||
ROMX_LOAD("epcbios1.bin", 0xe000, 0x02000, CRC(79a83706) SHA1(33528c46a24d7f65ef5a860fbed05afcf797fc55), ROM_BIOS(1))
|
||||
ROMX_LOAD("epcbios2.bin", 0xa000, 0x02000, CRC(3ca764ca) SHA1(02232fedef22d31a641f4b65933b9e269afce19e), ROM_BIOS(1))
|
||||
ROMX_LOAD("epcbios3.bin", 0xc000, 0x02000, CRC(70483280) SHA1(b44b09da94d77b0269fc48f07d130b2d74c4bb8f), ROM_BIOS(1))
|
||||
ROM_END
|
||||
|
||||
|
||||
COMP( 1985, epc, 0, 0, epc, epc_ports, epc_state, init_epc, "Ericsson Information System", "Ericsson PC" , MACHINE_NOT_WORKING )
|
||||
//COMP( 1985, eppc, ibm5150, 0, pccga, pccga, pc_state, empty_init, "Ericsson Information System", "Ericsson Portable PC", MACHINE_NOT_WORKING )
|
@ -46,7 +46,6 @@ public:
|
||||
void ncrpc4i(machine_config &config);
|
||||
void kaypro16(machine_config &config);
|
||||
void kaypropc(machine_config &config);
|
||||
void epc(machine_config &config);
|
||||
void m15(machine_config &config);
|
||||
void bondwell(machine_config &config);
|
||||
void siemens(machine_config &config);
|
||||
@ -86,7 +85,6 @@ private:
|
||||
static void cfg_single_360K(device_t *device);
|
||||
static void cfg_single_720K(device_t *device);
|
||||
|
||||
void epc_io(address_map &map);
|
||||
void ibm5550_io(address_map &map);
|
||||
void pc16_io(address_map &map);
|
||||
void pc16_map(address_map &map);
|
||||
@ -533,55 +531,6 @@ ROM_START( mc1702 )
|
||||
ROM_END
|
||||
|
||||
|
||||
/************************************************************** Ericsson PC ***
|
||||
|
||||
Links: https://youtu.be/6uilOdMJc24
|
||||
Form Factor: Desktop
|
||||
CPU: 8088 @ 4.77MHz
|
||||
RAM: 256K
|
||||
Bus: 6x ISA
|
||||
Video: Monchrome or Color 80x25 character mode. 320x200 and 640x400 (CGA?) grahics modes
|
||||
Display: Orange Gas Plasma (GP) display
|
||||
Mass storage: 2 x 5.25" 360K or 1 20Mb HDD
|
||||
On board ports: Beeper,
|
||||
Ports: serial, parallel
|
||||
Internal Options: Up to 640K RAM through add-on RAM card
|
||||
Misc: The hardware was not 100% PC compatible so non BIOS based software would not run. 50.000+ units sold
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
void pc_state::epc_io(address_map &map)
|
||||
{
|
||||
map.unmap_value_high();
|
||||
map(0x0000, 0x00ff).m("mb", FUNC(ibm5160_mb_device::map));
|
||||
map(0x0070, 0x0071).rw("i8251", FUNC(i8251_device::read), FUNC(i8251_device::write));
|
||||
}
|
||||
|
||||
void pc_state::epc(machine_config &config)
|
||||
{
|
||||
pccga(config);
|
||||
|
||||
i8088_cpu_device &maincpu(I8088(config.replace(), "maincpu", 4772720));
|
||||
maincpu.set_addrmap(AS_PROGRAM, &pc_state::pc8_map);
|
||||
maincpu.set_addrmap(AS_IO, &pc_state::epc_io);
|
||||
maincpu.set_irq_acknowledge_callback("mb:pic8259", FUNC(pic8259_device::inta_cb));
|
||||
|
||||
subdevice<isa8_slot_device>("isa1")->set_default_option("ega");
|
||||
I8251(config, "i8251", 0); // clock?
|
||||
}
|
||||
|
||||
ROM_START( epc )
|
||||
ROM_REGION(0x10000,"bios", 0)
|
||||
ROM_DEFAULT_BIOS("p860110")
|
||||
ROM_SYSTEM_BIOS(0, "p840705", "P840705")
|
||||
ROMX_LOAD("ericsson_8088.bin", 0xe000, 0x2000, CRC(3953c38d) SHA1(2bfc1f1d11d0da5664c3114994fc7aa3d6dd010d), ROM_BIOS(0))
|
||||
ROM_SYSTEM_BIOS(1, "p860110", "P860110")
|
||||
ROMX_LOAD("epcbios1.bin", 0xe000, 0x02000, CRC(79a83706) SHA1(33528c46a24d7f65ef5a860fbed05afcf797fc55), ROM_BIOS(1))
|
||||
ROMX_LOAD("epcbios2.bin", 0xa000, 0x02000, CRC(3ca764ca) SHA1(02232fedef22d31a641f4b65933b9e269afce19e), ROM_BIOS(1))
|
||||
ROMX_LOAD("epcbios3.bin", 0xc000, 0x02000, CRC(70483280) SHA1(b44b09da94d77b0269fc48f07d130b2d74c4bb8f), ROM_BIOS(1))
|
||||
ROM_END
|
||||
|
||||
|
||||
/************************************************ Ericsson Portable PC - EPPC ***
|
||||
|
||||
Links: https://youtu.be/Qmke4L4Jls8 , https://youtu.be/yXK01gBQE6Q
|
||||
@ -1358,7 +1307,6 @@ ROM_END
|
||||
|
||||
// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS
|
||||
COMP( 1984, dgone, ibm5150, 0, dgone, pccga, pc_state, empty_init, "Data General", "Data General/One" , MACHINE_NOT_WORKING )
|
||||
COMP( 1985, epc, ibm5150, 0, epc, pccga, pc_state, empty_init, "Ericsson Information System", "Ericsson PC" , MACHINE_NOT_WORKING )
|
||||
COMP( 1985, eppc, ibm5150, 0, pccga, pccga, pc_state, empty_init, "Ericsson Information System", "Ericsson Portable PC", MACHINE_NOT_WORKING )
|
||||
COMP( 1985, bw230, ibm5150, 0, bondwell, bondwell, pc_state, init_bondwell, "Bondwell Holding", "BW230 (PRO28 Series)", 0 )
|
||||
COMP( 1992, iskr3104, ibm5150, 0, iskr3104, pccga, pc_state, empty_init, "Schetmash", "Iskra 3104", MACHINE_NOT_WORKING )
|
||||
|
446
src/mame/machine/eispc_kb.cpp
Normal file
446
src/mame/machine/eispc_kb.cpp
Normal file
@ -0,0 +1,446 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders: Joakim Larsson Edström
|
||||
/**********************************************************************
|
||||
|
||||
Ericsson PC keyboard emulation
|
||||
|
||||
TTL-level bi-directional serial matrix keyboard
|
||||
|
||||
The mc6801 contains an internal ROM that handles scanning of the keyboard,
|
||||
controlling the 2 or 3 LEDs and also the programming of the scan code for
|
||||
a single programmable key.
|
||||
|
||||
There are two known variants of the keyboard. The first had the Ericsson
|
||||
internal name "Sgt Pepper" where the hardware was OEMed/manufactured by
|
||||
FACIT and had two LEDs while the second variant called "Roger Moore" had
|
||||
three LEDs and was manufactured by Ericsson.
|
||||
|
||||
Both keyboard hooks up directly to the port of a 6801 MCU. There are
|
||||
16 column lines driven by Port 3 and Port 4 that goes low one at a time
|
||||
during the scan process and when a key is pressed one of the six corresponding
|
||||
row lines goes low and fed to through a 74HC04 inverter into port 1, where a
|
||||
high bit means a key was pressed.
|
||||
|
||||
The connector has TX/Hold, Rx and Reset. Reset is connected directly to the
|
||||
MCU so the host CPU can keep it in RESET until it needs the keyboard.
|
||||
Rx is connected to the RX line of the SCI in the MCU, P23 - bit 3 of port 2.
|
||||
Tx/Hold is bidirectional, connected to the TX line of the SCI in the MCU, P24
|
||||
bit 4 of port 2, but can also be kept low by the host CPU to temporarily inhibit
|
||||
the keyboard from sending more scan codes. This is sensed by P16 through a
|
||||
74HC04 inverter.
|
||||
|
||||
The data is exchanged in both direction asynchronously at 1200 baud, 8 databits,
|
||||
1 start and 1 stop bit. At startup the host CPU sends a $00 (zero) byte to the
|
||||
keyboard simultaneously with the MCU sending a $A5 to the CPU to ensure full
|
||||
duplex operation. If the $A5 byte is not received EPC will display a "Keyboard
|
||||
Error" message on the screen.
|
||||
|
||||
P17 and P20 are connected to LEDs on Caps Lock and Num Lock keys. The latter
|
||||
keyboard variant Roger Moore also had a LED on Scroll Lock connected to P22.
|
||||
P20, P21 and P22 are pulled high to bring the MCU into MODE 7 at RESET. NMI
|
||||
and IRQ are pulled high and not connected to anything externally.
|
||||
|
||||
+--+--+--+--+--+-6x10K--o +5v
|
||||
+-------+ | | | | | |
|
||||
| P30|<------x--x--x--x--x--x--- COLUMNS x = 1N4448 diod towards P3/P4
|
||||
| P31|<------x--x--x--x--x--x--- x 16 in serie with key button
|
||||
| P32|<------x--x--x--x--x--x---
|
||||
| P33|<------x--x--x--x--x--x--- A pressed button pulls a P1 row
|
||||
| P34|<------x--x--x--x--x--x--- low when its P3/P4 column is
|
||||
| P35|<------x--x--x--x--x--x--- being scanned
|
||||
| P36|<------x--x--x--x--x--x---
|
||||
| P37|<------x--x--x--x--x--x---
|
||||
| P40|<------x--x--x--x--x--x---
|
||||
| P41|<------x--x--x--x--x--x---
|
||||
| P42|<------x--x--x--x--x--x---
|
||||
| P43|<------x--x--x--x--x--x---
|
||||
| P44|<------x--x--x--x--x--x---
|
||||
| P45|<------x--x--x--x--x--x---
|
||||
| P46|<------x--x--x--x--x--x---
|
||||
| P47|<------x--x--x--x--x--x---
|
||||
| | | | | | | |
|
||||
| M6801 | | | | | | |
|
||||
| | 6 x 74HC04 hex inverter
|
||||
|P10-P15|<------+--+--+--+--+--+ ROWS x 6
|
||||
+-------+
|
||||
|
||||
Credits
|
||||
-------
|
||||
The internal ROM was dumped in collaboration with Dalby Datormuseum, whom
|
||||
also provided documentation and schematics of the keyboard
|
||||
|
||||
https://sites.google.com/site/dalbydatormuseum/home
|
||||
https://github.com/MattisLind/6801reader
|
||||
|
||||
**********************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "eispc_kb.h"
|
||||
#include "cpu/m6800/m6801.h"
|
||||
|
||||
//**************************************************************************
|
||||
// CONFIGURABLE LOGGING
|
||||
//**************************************************************************
|
||||
#define LOG_PORTS (1U << 1)
|
||||
#define LOG_RESET (1U << 2)
|
||||
#define LOG_BITS (1U << 3)
|
||||
#define LOG_UI (1U << 4)
|
||||
|
||||
//#define VERBOSE (LOG_UI)
|
||||
//#define LOG_OUTPUT_STREAM std::cout
|
||||
|
||||
#include "logmacro.h"
|
||||
|
||||
#define LOGPORTS(...) LOGMASKED(LOG_PORTS, __VA_ARGS__)
|
||||
#define LOGRST(...) LOGMASKED(LOG_RESET, __VA_ARGS__)
|
||||
#define LOGBITS(...) LOGMASKED(LOG_BITS, __VA_ARGS__)
|
||||
#define LOGUI(...) LOGMASKED(LOG_UI, __VA_ARGS__)
|
||||
|
||||
//**************************************************************************
|
||||
// MACROS / CONSTANTS
|
||||
//**************************************************************************
|
||||
|
||||
#define M6801_TAG "mcu"
|
||||
|
||||
#define PCM(handler, parameter) PORT_CHANGED_MEMBER(DEVICE_SELF, eispc_keyboard_device, handler, parameter)
|
||||
|
||||
namespace {
|
||||
|
||||
INPUT_PORTS_START(eispc_kb)
|
||||
PORT_START("P15")
|
||||
PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("KP 6") PORT_CODE(KEYCODE_6_PAD) PORT_CODE(KEYCODE_RIGHT) PORT_CHAR('6') PORT_CHAR(UCHAR_MAMEKEY(RIGHT)) PCM(key, 0) // 77
|
||||
PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("KP +") PORT_CODE(KEYCODE_PLUS_PAD) PORT_CHAR('+') PCM(key, 0) // 78
|
||||
PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("KP 5") PORT_CODE(KEYCODE_5_PAD) PORT_CHAR('5') PCM(key, 0) // 76
|
||||
PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("* PRINT") PORT_CODE(KEYCODE_TILDE) PORT_CHAR('*') PORT_CHAR(UCHAR_MAMEKEY(PRTSCR)) PCM(key, 0) // 55
|
||||
PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("R Shift") PORT_CODE(KEYCODE_RSHIFT) PORT_CHAR(UCHAR_SHIFT_1) PCM(key, 0) // 54
|
||||
PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-') PORT_CHAR('_') PCM(key, 0) // 53
|
||||
PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(". :") PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR(':') PCM(key, 0) // 52
|
||||
PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("F5") PORT_CODE(KEYCODE_F5) PORT_CHAR(UCHAR_MAMEKEY(F5)) PCM(key, 0) // 63
|
||||
PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("F6") PORT_CODE(KEYCODE_F6) PORT_CHAR(UCHAR_MAMEKEY(F6)) PCM(key, 0) // 64
|
||||
PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_UNUSED ) PCM(key, 0) // no scancode is sent
|
||||
PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("CTRL") PORT_CODE(KEYCODE_LCONTROL) PORT_CHAR(UCHAR_MAMEKEY(LCONTROL)) PCM(key, 0) // 29
|
||||
PORT_BIT( 0x0800, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(", ;") PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR(';') PCM(key, 0) // 51
|
||||
PORT_BIT( 0x1000, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_D) PORT_CHAR('D') PORT_CHAR('d') PCM(key, 0) // 32
|
||||
PORT_BIT( 0x2000, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_X) PORT_CHAR('X') PORT_CHAR('x') PCM(key, 0) // 45
|
||||
PORT_BIT( 0x4000, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_C) PORT_CHAR('C') PORT_CHAR('c') PCM(key, 0) // 46
|
||||
PORT_BIT( 0x8000, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_J) PORT_CHAR('J') PORT_CHAR('j') PCM(key, 0) // 36
|
||||
|
||||
PORT_START("P14")
|
||||
PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_UNUSED ) PCM(key, 1) // 00 - keyboard error
|
||||
PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("BREAK") PORT_CODE(KEYCODE_PAUSE) PORT_CHAR(UCHAR_MAMEKEY(PAUSE)) PCM(key, 1) // 70
|
||||
PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("KP 7") PORT_CODE(KEYCODE_7_PAD) PORT_CHAR('7') PORT_CHAR(UCHAR_MAMEKEY(HOME)) PCM(key, 1) // 71
|
||||
PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_UNUSED ) PCM(key, 1) // ff - keyboard error
|
||||
PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_TILDE) PORT_CHAR('^') PORT_CHAR('~') PORT_CHAR(']') PCM(key, 1) // 27
|
||||
PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR(0x00e5) PORT_CHAR(0x00c5) PORT_CHAR('[') PCM(key, 1) // 26 å Å
|
||||
PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_P) PORT_CHAR('P') PORT_CHAR('p') PCM(key, 1) // 25
|
||||
PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("F1") PORT_CODE(KEYCODE_F1) PORT_CHAR(UCHAR_MAMEKEY(F1)) PCM(key, 1) // 59
|
||||
PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("F2") PORT_CODE(KEYCODE_F2) PORT_CHAR(UCHAR_MAMEKEY(F2)) PCM(key, 1) // 60
|
||||
PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_W) PORT_CHAR('w') PORT_CHAR('W') PCM(key, 1) // 17
|
||||
PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_E) PORT_CHAR('e') PORT_CHAR('E') PCM(key, 1) // 18
|
||||
PORT_BIT( 0x0800, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O') PCM(key, 1) // 24
|
||||
PORT_BIT( 0x1000, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_R) PORT_CHAR('r') PORT_CHAR('R') PCM(key, 1) // 19
|
||||
PORT_BIT( 0x2000, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_T) PORT_CHAR('t') PORT_CHAR('T') PCM(key, 1) // 20
|
||||
PORT_BIT( 0x4000, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_Y) PORT_CHAR('y') PORT_CHAR('Y') PCM(key, 1) // 21
|
||||
PORT_BIT( 0x8000, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_I) PORT_CHAR('i') PORT_CHAR('I') PCM(key, 1) // 23
|
||||
|
||||
PORT_START("P13")
|
||||
PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_NUMLOCK) PORT_CHAR(UCHAR_MAMEKEY(NUMLOCK)) PCM(key, 2) // 69
|
||||
PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_UNUSED ) PCM(key, 2) // ff - keyboard error
|
||||
PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("BS DEL") PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(8) PORT_CHAR(UCHAR_MAMEKEY(DEL)) PCM(key, 2) // 14
|
||||
PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('=') PORT_CHAR('+') PCM(key, 2) // 13
|
||||
PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-') PORT_CHAR('_') PCM(key, 2) // 12
|
||||
PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR(')') PCM(key, 2) // 11
|
||||
PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR('(') PCM(key, 2) // 10
|
||||
PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!') PCM(key, 2) // 02
|
||||
PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("ESC") PORT_CODE(KEYCODE_ESC) PORT_CHAR(UCHAR_MAMEKEY(ESC)) PCM(key, 2) // 01
|
||||
PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('@') PCM(key, 2) // 03
|
||||
PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('#') PCM(key, 2) // 04
|
||||
PORT_BIT( 0x0800, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('*') PCM(key, 2) // 09
|
||||
PORT_BIT( 0x1000, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$') PCM(key, 2) // 05
|
||||
PORT_BIT( 0x2000, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%') PCM(key, 2) // 06
|
||||
PORT_BIT( 0x4000, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('^') PCM(key, 2) // 07
|
||||
PORT_BIT( 0x8000, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('&') PCM(key, 2) // 08
|
||||
|
||||
PORT_START("P12")
|
||||
PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("KP 9") PORT_CODE(KEYCODE_9_PAD) PORT_CHAR('9') PORT_CHAR(UCHAR_MAMEKEY(PGUP)) PCM(key, 3) // 73
|
||||
PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("KP -") PORT_CODE(KEYCODE_MINUS_PAD) PORT_CHAR(UCHAR_MAMEKEY(MINUS_PAD)) PCM(key, 3) // 74
|
||||
PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("KP 8") PORT_CODE(KEYCODE_8_PAD) PORT_CODE(KEYCODE_UP) PORT_CHAR('8') PORT_CHAR(UCHAR_MAMEKEY(UP)) PCM(key, 3) // 72
|
||||
PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_TILDE) PORT_CHAR('`') PORT_CHAR('~') PCM(key, 3) // 41
|
||||
PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR('\'') PORT_CHAR('"') PCM(key, 3) // 40
|
||||
PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_COLON) PORT_CHAR(';') PORT_CHAR(':') PCM(key, 3) // 39
|
||||
PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_L) PORT_CHAR('l') PORT_CHAR('L') PCM(key, 3) // 38
|
||||
PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("F3") PORT_CODE(KEYCODE_F3) PORT_CHAR(UCHAR_MAMEKEY(F3)) PCM(key, 3) // 61
|
||||
PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("F4") PORT_CODE(KEYCODE_F4) PORT_CHAR(UCHAR_MAMEKEY(F4)) PCM(key, 3) // 62
|
||||
PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q') PCM(key, 3) // 16
|
||||
PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("TAB") PORT_CODE(KEYCODE_TAB) PORT_CHAR(9) PCM(key, 3) // 15
|
||||
PORT_BIT( 0x0800, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_K) PORT_CHAR('k') PORT_CHAR('K') PCM(key, 3) // 37
|
||||
PORT_BIT( 0x1000, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F) PORT_CHAR('f') PORT_CHAR('F') PCM(key, 3) // 33
|
||||
PORT_BIT( 0x2000, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_G) PORT_CHAR('g') PORT_CHAR('G') PCM(key, 3) // 34
|
||||
PORT_BIT( 0x4000, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_H) PORT_CHAR('h') PORT_CHAR('H') PCM(key, 3) // 35
|
||||
PORT_BIT( 0x8000, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_U) PORT_CHAR('u') PORT_CHAR('U') PCM(key, 3) // 22
|
||||
|
||||
PORT_START("P11")
|
||||
PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_DEL_PAD) PORT_CHAR(UCHAR_MAMEKEY(COMMA_PAD)) PCM(key, 4) // 83
|
||||
PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("RETURN") PORT_CODE(KEYCODE_ENTER) PORT_CHAR(13) PCM(key, 4) // 28
|
||||
PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("KP 0") PORT_CODE(KEYCODE_0_PAD) PORT_CHAR('0') PORT_CHAR(UCHAR_MAMEKEY(INSERT)) PCM(key, 4) // 82
|
||||
PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_UNUSED ) PCM(key, 4) // 89 - no key
|
||||
PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_UNUSED ) PCM(key, 4) // 86 - no key
|
||||
PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_UNUSED ) PCM(key, 4) // 87 - no key
|
||||
PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_UNUSED ) PCM(key, 4) // 88 - no key
|
||||
PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("F9") PORT_CODE(KEYCODE_F9) PORT_CHAR(UCHAR_MAMEKEY(F9)) PCM(key, 4) // 67
|
||||
PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("F10") PORT_CODE(KEYCODE_F10) PORT_CHAR(UCHAR_MAMEKEY(F10)) PCM(key, 4) // 68
|
||||
PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_UNUSED ) PCM(key, 4) // scan code ff - keyboard error
|
||||
PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR('\\') PCM(key, 4) // 43
|
||||
PORT_BIT( 0x0800, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("CAPS LOCK") PORT_CODE(KEYCODE_CAPSLOCK) PORT_CHAR(UCHAR_MAMEKEY(CAPSLOCK)) PCM(key, 4) // 58
|
||||
PORT_BIT( 0x1000, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("SHIFT LOCK") PORT_CODE(KEYCODE_LALT) PCM(key, 4) // 56
|
||||
PORT_BIT( 0x2000, IP_ACTIVE_LOW, IPT_UNUSED ) PCM(key, 4) // 85 - no key
|
||||
PORT_BIT( 0x4000, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V') PCM(key, 4) // 47
|
||||
PORT_BIT( 0x8000, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ') PCM(key, 4) // 57
|
||||
|
||||
PORT_START("P10")
|
||||
PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("KP 3") PORT_CODE(KEYCODE_3_PAD) PORT_CODE(KEYCODE_PGDN) PCM(key, 5) // 81
|
||||
PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_UNUSED ) PCM(key, 5) // ff - keyboard error
|
||||
PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("KP 2") PORT_CODE(KEYCODE_2_PAD) PORT_CODE(KEYCODE_DOWN) PORT_CHAR(UCHAR_MAMEKEY(2_PAD)) PCM(key, 5) // 80
|
||||
PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("NEW LINE") PORT_CODE(KEYCODE_ENTER_PAD) PORT_CHAR(UCHAR_MAMEKEY(ENTER_PAD)) PCM(key, 5) // 84 (programmable, default is 28)
|
||||
PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("KP 1") PORT_CODE(KEYCODE_1_PAD) PORT_CHAR(UCHAR_MAMEKEY(1_PAD)) PCM(key, 5) // 79
|
||||
PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("KP 4") PORT_CODE(KEYCODE_4_PAD) PORT_CODE(KEYCODE_LEFT) PORT_CHAR('4') PORT_CHAR(UCHAR_MAMEKEY(LEFT)) PCM(key, 5) // 75
|
||||
PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_UNUSED ) PCM(key, 5) // ff - keyboard error
|
||||
PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("F7") PORT_CODE(KEYCODE_F7) PORT_CHAR(UCHAR_MAMEKEY(F7)) PCM(key, 5) // 65
|
||||
PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("F8") PORT_CODE(KEYCODE_F8) PORT_CHAR(UCHAR_MAMEKEY(F8)) PCM(key, 5) // 66
|
||||
PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_LSHIFT) PORT_CHAR(UCHAR_SHIFT_1) PCM(key, 5) // 42
|
||||
PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_Z) PORT_CHAR('z') PORT_CHAR('Z') PCM(key, 5) // 44
|
||||
PORT_BIT( 0x0800, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_M) PORT_CHAR('m') PORT_CHAR('M') PCM(key, 5) // 50
|
||||
PORT_BIT( 0x1000, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_A) PORT_CHAR('a') PORT_CHAR('A') PCM(key, 5) // 30
|
||||
PORT_BIT( 0x2000, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_S) PORT_CHAR('s') PORT_CHAR('S') PCM(key, 5) // 31
|
||||
PORT_BIT( 0x4000, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_B) PORT_CHAR('b') PORT_CHAR('B') PCM(key, 5) // 48
|
||||
PORT_BIT( 0x8000, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_N) PORT_CHAR('n') PORT_CHAR('N') PCM(key, 5) // 49
|
||||
INPUT_PORTS_END
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// ROM( eispc_kb )
|
||||
//-------------------------------------------------
|
||||
|
||||
ROM_START( eispc_kb )
|
||||
ROM_REGION( 0x800, M6801_TAG, 0 )
|
||||
ROM_LOAD( "sgtpepper-1.2.bin", 0x000, 0x800, CRC(7107b841) SHA1(a939dd50622575c31fea9c7adb7a7db5403a7aca) )
|
||||
ROM_END
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
//**************************************************************************
|
||||
// DEVICE DEFINITIONS
|
||||
//**************************************************************************
|
||||
|
||||
DEFINE_DEVICE_TYPE(EISPC_KB, eispc_keyboard_device, "eispc_kb", "Ericsson PC keyboard")
|
||||
|
||||
//**************************************************************************
|
||||
// LIVE DEVICE
|
||||
//**************************************************************************
|
||||
|
||||
//-------------------------------------------------
|
||||
// eispc_keyboard_device - constructor
|
||||
//-------------------------------------------------
|
||||
|
||||
eispc_keyboard_device::eispc_keyboard_device(
|
||||
machine_config const &mconfig,
|
||||
char const *tag,
|
||||
device_t *owner,
|
||||
uint32_t clock)
|
||||
: device_t(mconfig, EISPC_KB, tag, owner, clock)
|
||||
, m_mcu(*this, M6801_TAG)
|
||||
, m_rows(*this, "P1%u", 0)
|
||||
, m_txd_cb(*this)
|
||||
, m_rxd_high(true)
|
||||
, m_txd_high(true)
|
||||
, m_hold(true)
|
||||
, m_col_select(0)
|
||||
{
|
||||
}
|
||||
|
||||
INPUT_CHANGED_MEMBER( eispc_keyboard_device::key )
|
||||
{
|
||||
if (oldval && !newval)
|
||||
{
|
||||
LOGUI("Key Pressed - name: %s field: %04x param: %04x oldval: %04x newval: %04x\n", field.name(), field.defvalue(), param, oldval, newval);
|
||||
int idx = *((int *)(¶m));
|
||||
if (idx >= sizeof(keys))
|
||||
logerror("Out of bounds access in keys array\n");
|
||||
else
|
||||
keys[idx] |= (uint16_t) field.defvalue();
|
||||
}
|
||||
else if (newval && !oldval)
|
||||
{
|
||||
LOGUI("Key Released - name: %s field: %04x param: %04x oldval: %04x newval: %04x\n", field.name(), field.defvalue(), param, oldval, newval);
|
||||
int idx = *((int *)(¶m));
|
||||
if (idx >= sizeof(keys))
|
||||
logerror("Out of bounds access in keys array\n");
|
||||
else
|
||||
keys[idx] &= ~(uint16_t)field.defvalue();
|
||||
}
|
||||
for (int i = 0; i < 6; i++) LOGUI("%04x ", keys[i]); LOGUI("\n");
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER(eispc_keyboard_device::rxd_w)
|
||||
{
|
||||
LOGBITS("KBD bit presented: %d\n", state);
|
||||
m_rxd_high = CLEAR_LINE != state;
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER(eispc_keyboard_device::hold_w)
|
||||
{
|
||||
m_hold = CLEAR_LINE == state;
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER(eispc_keyboard_device::rst_line_w)
|
||||
{
|
||||
if (state == CLEAR_LINE)
|
||||
{
|
||||
m_mcu->resume(SUSPEND_REASON_RESET);
|
||||
LOGRST("KBD: Keyboard mcu reset line is cleared\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
m_mcu->suspend(SUSPEND_REASON_RESET, 0);
|
||||
LOGRST("KBD: Keyboard mcu reset line is asserted\n");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_reset - device-specific reset
|
||||
//-------------------------------------------------
|
||||
|
||||
void eispc_keyboard_device::device_reset()
|
||||
{
|
||||
LOGRST("KBD: Keyboard is in reset until host computer explicitly releases the reset line\n");
|
||||
m_mcu->suspend(SUSPEND_REASON_RESET, 0);
|
||||
for (auto & elem : keys) elem = 0;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_start - device-specific startup
|
||||
//-------------------------------------------------
|
||||
|
||||
void eispc_keyboard_device::device_start()
|
||||
{
|
||||
m_txd_cb.resolve_safe();
|
||||
|
||||
save_item(NAME(m_rxd_high));
|
||||
save_item(NAME(m_txd_high));
|
||||
save_item(NAME(m_col_select));
|
||||
|
||||
m_rxd_high = true;
|
||||
m_txd_high = true;
|
||||
m_col_select = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_add_mconfig - add device configuration
|
||||
//-------------------------------------------------
|
||||
|
||||
void eispc_keyboard_device::device_add_mconfig(machine_config &config)
|
||||
{
|
||||
M6801(config, m_mcu, XTAL(4'915'200)); // Crystal verified from schematics and visual inspection
|
||||
m_mcu->set_addrmap(AS_PROGRAM, &eispc_keyboard_device::eispc_kb_mem);
|
||||
|
||||
m_mcu->in_p1_cb().set([this]
|
||||
{
|
||||
uint8_t data = 0; // Indicate what keys are pressed in selected column
|
||||
|
||||
for (int i = 0; i < 6; i++) data |= (keys[i] & m_col_select ? 1 << i : 0);
|
||||
|
||||
// Update txd bit
|
||||
data &= 0x3f;
|
||||
data |= ((!m_hold || !m_txd_high) ? 0 : 0x40);
|
||||
|
||||
if ((data & 0x3f) != 0 && data != m_p1)
|
||||
{
|
||||
LOGUI("Reading port 1: %02x m_col_select:%04x\n", data, m_col_select);
|
||||
m_p1 = data;
|
||||
}
|
||||
return data;
|
||||
});
|
||||
|
||||
m_mcu->out_p1_cb().set([this](uint8_t data)
|
||||
{
|
||||
LOGPORTS("Writing %02x PORT 1\n", data);
|
||||
});
|
||||
|
||||
m_mcu->in_p2_cb().set([this]
|
||||
{
|
||||
uint8_t data = M6801_MODE_7 | (m_rxd_high ? (1 << 3) : 0);
|
||||
LOGPORTS("Reading port 2: %02x\n", data);
|
||||
//LOGBITS("KBD: Reading rxd_high: %02x\n", m_rxd_high);
|
||||
return data;
|
||||
});
|
||||
|
||||
m_mcu->out_p2_cb().set([this](uint8_t data)
|
||||
{
|
||||
LOGPORTS("Writing port 2: %02x\n", data);
|
||||
LOGBITS("KBD: writing bit: %02x\n", BIT(data, 4));
|
||||
});
|
||||
|
||||
m_mcu->out_ser_tx_cb().set([this](bool state)
|
||||
{
|
||||
m_txd_high = CLEAR_LINE != state;
|
||||
LOGBITS("KBD: writing bit: %02x\n", m_txd_high);
|
||||
m_txd_cb(state);
|
||||
});
|
||||
|
||||
m_mcu->in_p3_cb().set([this]
|
||||
{
|
||||
LOGPORTS("Reading Port 3\n");
|
||||
return 0x00;
|
||||
});
|
||||
|
||||
m_mcu->out_p3_cb().set([this](uint8_t data)
|
||||
{
|
||||
m_col_select &= 0xff00;
|
||||
m_col_select |= ~data;
|
||||
});
|
||||
|
||||
m_mcu->in_p4_cb().set([this]
|
||||
{
|
||||
LOGPORTS("Reading Port 4\n");
|
||||
return 0x00;
|
||||
});
|
||||
|
||||
m_mcu->out_p4_cb().set([this](uint8_t data)
|
||||
{
|
||||
m_col_select &= 0x00ff;
|
||||
m_col_select |= (~data << 8);
|
||||
});
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// input_ports - device-specific input ports
|
||||
//-------------------------------------------------
|
||||
|
||||
ioport_constructor eispc_keyboard_device::device_input_ports() const
|
||||
{
|
||||
return INPUT_PORTS_NAME( eispc_kb );
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// ADDRESS_MAP( eispc_kb_mem )
|
||||
//-------------------------------------------------
|
||||
|
||||
void eispc_keyboard_device::eispc_kb_mem(address_map &map)
|
||||
{
|
||||
map(0x0000, 0x001f).rw(M6801_TAG, FUNC(m6801_cpu_device::m6801_io_r), FUNC(m6801_cpu_device::m6801_io_w));
|
||||
map(0x0080, 0x00ff).ram();
|
||||
map(0xf800, 0xffff).rom().region(M6801_TAG, 0);
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// rom_region - device-specific ROM region
|
||||
//-------------------------------------------------
|
||||
|
||||
const tiny_rom_entry *eispc_keyboard_device::device_rom_region() const
|
||||
{
|
||||
return ROM_NAME( eispc_kb );
|
||||
}
|
45
src/mame/machine/eispc_kb.h
Normal file
45
src/mame/machine/eispc_kb.h
Normal file
@ -0,0 +1,45 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Joakim Larsson Edström
|
||||
#ifndef MAME_MACHINE_EISPC_KB_H
|
||||
#define MAME_MACHINE_EISPC_KB_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cpu/m6800/m6801.h"
|
||||
|
||||
DECLARE_DEVICE_TYPE(EISPC_KB, eispc_keyboard_device)
|
||||
|
||||
class eispc_keyboard_device : public device_t
|
||||
{
|
||||
public:
|
||||
auto txd_cb() { return m_txd_cb.bind(); }
|
||||
|
||||
eispc_keyboard_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock = 0);
|
||||
|
||||
DECLARE_INPUT_CHANGED_MEMBER(key);
|
||||
DECLARE_WRITE_LINE_MEMBER(rxd_w);
|
||||
DECLARE_WRITE_LINE_MEMBER(hold_w);
|
||||
DECLARE_WRITE_LINE_MEMBER(rst_line_w);
|
||||
|
||||
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;
|
||||
virtual tiny_rom_entry const *device_rom_region() const override;
|
||||
|
||||
required_device<m6801_cpu_device> m_mcu;
|
||||
required_ioport_array<6> m_rows;
|
||||
devcb_write_line m_txd_cb; // Callback for KBD-> EPC
|
||||
|
||||
bool m_rxd_high; // state of Rx input line
|
||||
bool m_txd_high; // state of Tx output line
|
||||
bool m_hold;
|
||||
uint16_t m_col_select;
|
||||
uint16_t keys[6];
|
||||
uint8_t m_p1;
|
||||
|
||||
void eispc_kb_mem(address_map &map);
|
||||
};
|
||||
|
||||
#endif // MAME_MACHINE_EISPC_KB_H
|
@ -12715,6 +12715,9 @@ splndrbt2 // (c) 1985 Alpha Denshi Co.
|
||||
splndrbta // (c) 1985 Alpha Denshi Co.
|
||||
splndrbtb // (c) 1985 Alpha Denshi Co.
|
||||
|
||||
@source:eispc.cpp
|
||||
epc // 1984 Ericsson PC
|
||||
|
||||
@source:ertictac.cpp
|
||||
ertictac // (c) 1992 Sisteme
|
||||
ertictaca // (c) 1992 Sisteme
|
||||
@ -31659,7 +31662,6 @@ comport // Compaq Portable
|
||||
dgone // 1984 Data General/One
|
||||
eagle1600 //
|
||||
eaglespirit // Eagle PC Spirit
|
||||
epc // 1984 Ericsson PC
|
||||
eppc // 1985 Ericsson Portable PC
|
||||
hyo88t // Hyosung Topstar 88T
|
||||
ibm5550 //
|
||||
|
@ -220,6 +220,7 @@ ec184x.cpp
|
||||
ec65.cpp
|
||||
ec7915.cpp
|
||||
einstein.cpp
|
||||
eispc.cpp
|
||||
elan_eu3a05.cpp
|
||||
elan_eu3a14.cpp
|
||||
electron.cpp
|
||||
|
Loading…
Reference in New Issue
Block a user