mirror of
https://github.com/holub/mame
synced 2025-04-19 07:00:31 +03:00
New skeleton: GRiD Compass series
This commit is contained in:
parent
7044a6b5fc
commit
24d016f62c
@ -1024,6 +1024,18 @@ if (MACHINES["I2CMEM"]~=null) then
|
||||
}
|
||||
end
|
||||
|
||||
---------------------------------------------------
|
||||
--
|
||||
--@src/devices/machine/i7220.h,MACHINES["I7220"] = true
|
||||
---------------------------------------------------
|
||||
|
||||
if (MACHINES["I7220"]~=null) then
|
||||
files {
|
||||
MAME_DIR .. "src/devices/machine/i7220.cpp",
|
||||
MAME_DIR .. "src/devices/machine/i7220.h",
|
||||
}
|
||||
end
|
||||
|
||||
---------------------------------------------------
|
||||
--
|
||||
--@src/devices/machine/i8155.h,MACHINES["I8155"] = true
|
||||
|
@ -415,6 +415,7 @@ MACHINES["HD63450"] = true
|
||||
MACHINES["HD64610"] = true
|
||||
MACHINES["HP_TACO"] = true
|
||||
MACHINES["I2CMEM"] = true
|
||||
MACHINES["I7220"] = true
|
||||
MACHINES["I80130"] = true
|
||||
MACHINES["I8089"] = true
|
||||
MACHINES["I8155"] = true
|
||||
@ -955,6 +956,7 @@ function linkProjects_mame_mess(_target, _subtarget)
|
||||
"galaxy",
|
||||
"gamepark",
|
||||
"gi",
|
||||
"gridcomp",
|
||||
"grundy",
|
||||
"hartung",
|
||||
"heathkit",
|
||||
@ -1998,6 +2000,13 @@ files {
|
||||
MAME_DIR .. "src/mame/drivers/hh_pic16.cpp",
|
||||
}
|
||||
|
||||
createMESSProjects(_target, _subtarget, "gridcomp")
|
||||
files {
|
||||
MAME_DIR .. "src/mame/drivers/gridcomp.cpp",
|
||||
MAME_DIR .. "src/mame/machine/gridkeyb.cpp",
|
||||
MAME_DIR .. "src/mame/machine/gridkeyb.h",
|
||||
}
|
||||
|
||||
createMESSProjects(_target, _subtarget, "grundy")
|
||||
files {
|
||||
MAME_DIR .. "src/mame/drivers/newbrain.cpp",
|
||||
|
710
src/devices/machine/i7220.cpp
Normal file
710
src/devices/machine/i7220.cpp
Normal file
@ -0,0 +1,710 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Sergey Svishchev
|
||||
/**********************************************************************
|
||||
|
||||
Intel 7220 Bubble Memory Controller emulation
|
||||
|
||||
References:
|
||||
- http://www.decadecounter.com/vta/pdf/BPK72UM.pdf
|
||||
- http://www.decadecounter.com/vta/pdf/7220-1.pdf
|
||||
- http://www.decadecounter.com/vta/pdf/7242.pdf
|
||||
- http://www.decadecounter.com/vta/articleview.php?item=359
|
||||
|
||||
Implemented at least partially
|
||||
- commands
|
||||
Read Bubble Data, Write Bubble Data
|
||||
Initialize, Reset FIFO, Abort, Software Reset
|
||||
Read FSA Status, MBM Purge
|
||||
|
||||
Not implemented
|
||||
- interrupts
|
||||
- DMA
|
||||
- commands
|
||||
Read Seek, Write Seek, Read Corrected Data, all Bootloop-related
|
||||
- access to other than 2 FSA channels at once
|
||||
|
||||
**********************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "i7220.h"
|
||||
|
||||
|
||||
#define VERBOSE_DBG 2 /* general debug messages */
|
||||
|
||||
#define DBG_LOG(N,M,A) \
|
||||
do { \
|
||||
if(VERBOSE_DBG>=N) \
|
||||
{ \
|
||||
if( M ) \
|
||||
logerror("%11.6f at %s: %-10s",machine().time().as_double(),machine().describe_context(),(char*)M ); \
|
||||
logerror A; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
||||
// device type definition
|
||||
DEFINE_DEVICE_TYPE(I7220, i7220_device, "i7220", "Intel 7220 BMC")
|
||||
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// HELPERS
|
||||
//**************************************************************************
|
||||
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// LIVE DEVICE
|
||||
//**************************************************************************
|
||||
|
||||
//-------------------------------------------------
|
||||
// i7220_device - constructor
|
||||
//-------------------------------------------------
|
||||
|
||||
i7220_device::i7220_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
||||
: device_t(mconfig, I7220, tag, owner, clock)
|
||||
, device_image_interface(mconfig, *this)
|
||||
, intrq_cb(*this)
|
||||
, drq_cb(*this)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_start - device-specific startup
|
||||
//-------------------------------------------------
|
||||
|
||||
void i7220_device::device_start()
|
||||
{
|
||||
// resolve callbacks
|
||||
intrq_cb.resolve_safe();
|
||||
drq_cb.resolve_safe();
|
||||
|
||||
bi.tm = timer_alloc(0);
|
||||
|
||||
// register for state saving
|
||||
save_item(NAME(m_regs));
|
||||
save_item(NAME(m_rac));
|
||||
save_item(NAME(m_cmdr));
|
||||
save_item(NAME(m_str));
|
||||
save_item(NAME(m_blr));
|
||||
save_item(NAME(m_ar));
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_reset - device-specific startup
|
||||
//-------------------------------------------------
|
||||
|
||||
void i7220_device::device_reset()
|
||||
{
|
||||
main_phase = PHASE_IDLE;
|
||||
bi.main_state = IDLE;
|
||||
bi.sub_state = IDLE;
|
||||
|
||||
set_drq(false);
|
||||
set_irq(false);
|
||||
fifo_clear();
|
||||
|
||||
m_rac = m_cmdr = m_str = m_blr = m_ar = 0;
|
||||
memset(&m_regs, 0, sizeof(m_regs));
|
||||
}
|
||||
|
||||
void i7220_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
|
||||
{
|
||||
general_continue(bi);
|
||||
}
|
||||
|
||||
image_init_result i7220_device::call_load()
|
||||
{
|
||||
if (length() != (m_data_size * I7110_MBM_SIZE))
|
||||
{
|
||||
return image_init_result::FAIL;
|
||||
}
|
||||
return image_init_result::PASS;
|
||||
}
|
||||
|
||||
|
||||
void i7220_device::set_drq(bool state)
|
||||
{
|
||||
if (state != drq)
|
||||
{
|
||||
drq = state;
|
||||
drq_cb(drq);
|
||||
}
|
||||
}
|
||||
|
||||
void i7220_device::set_irq(bool state)
|
||||
{
|
||||
if (state != irq)
|
||||
{
|
||||
irq = state;
|
||||
intrq_cb(irq);
|
||||
}
|
||||
}
|
||||
|
||||
void i7220_device::update_drq()
|
||||
{
|
||||
switch (bi.main_state)
|
||||
{
|
||||
case READ_DATA:
|
||||
set_drq(m_fifo_size < 22 ? false : true);
|
||||
break;
|
||||
|
||||
case WRITE_DATA:
|
||||
set_drq(m_fifo_size < (40 - 22) ? true : false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void i7220_device::fifo_clear()
|
||||
{
|
||||
m_fifo.clear();
|
||||
m_fifo_size = 0;
|
||||
set_drq(false);
|
||||
}
|
||||
|
||||
uint8_t i7220_device::fifo_pop()
|
||||
{
|
||||
uint8_t val;
|
||||
|
||||
if (m_fifo.empty())
|
||||
{
|
||||
return m_fifo.dequeue();
|
||||
}
|
||||
else
|
||||
{
|
||||
val = m_fifo.dequeue();
|
||||
m_fifo_size--;
|
||||
if (main_phase == PHASE_EXEC)
|
||||
{
|
||||
update_drq();
|
||||
}
|
||||
return val;
|
||||
}
|
||||
}
|
||||
|
||||
void i7220_device::fifo_push(uint8_t val)
|
||||
{
|
||||
if (m_fifo.full())
|
||||
{
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_fifo.enqueue(val);
|
||||
m_fifo_size++;
|
||||
if (main_phase == PHASE_EXEC)
|
||||
{
|
||||
update_drq();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void i7220_device::update_regs()
|
||||
{
|
||||
m_blr = (m_regs[R_BLR_M] << 8) + m_regs[R_BLR_L];
|
||||
m_ar = (m_regs[R_AR_M] << 8) + m_regs[R_AR_L];
|
||||
blr_count = m_blr & 0x7ff;
|
||||
blr_nfc = (m_blr >> 12) ? ((m_blr >> 12) << 1) : 1;
|
||||
ar_addr = m_ar & 0x7ff;
|
||||
ar_mbm = (m_ar >> 11) & 15;
|
||||
}
|
||||
|
||||
|
||||
void i7220_device::start_command(int cmd)
|
||||
{
|
||||
main_phase = PHASE_EXEC;
|
||||
m_str &= ~SR_CLEAR;
|
||||
|
||||
switch (cmd)
|
||||
{
|
||||
// determines how many FSAs are present, reads and decodes bootloop from each MBM and stores result in FSA bootloop regs.
|
||||
// all parametric registers must be properly set up before issuing Initialize command.
|
||||
// NFC bits in BLR MSB must be set to 0001 before issuing this command.
|
||||
// MBM GROUP SELECT bits in the AR must select the last MBM in the system.
|
||||
case C_INIT:
|
||||
DBG_LOG(1, "BMC", ("INIT: BLR %04x (NFC %d pages %d) AR %04x (MBM %d addr %03x) ER %02d\n",
|
||||
m_blr, blr_nfc, blr_count, m_ar, ar_mbm, ar_addr, m_regs[R_ER]));
|
||||
if (blr_nfc != 2)
|
||||
{
|
||||
command_fail_start(bi);
|
||||
}
|
||||
else
|
||||
{
|
||||
init_start(bi);
|
||||
}
|
||||
break;
|
||||
|
||||
case C_READ_FSA_STATUS:
|
||||
read_fsa_start(bi);
|
||||
break;
|
||||
|
||||
// all parametric registers must be properly set up before issuing Read Bubble Data command
|
||||
case C_READ:
|
||||
DBG_LOG(1, "BMC", ("RBD: BLR %04x (NFC %d pages %d) AR %04x (MBM %d addr %03x) ER %02d\n",
|
||||
m_blr, blr_nfc, blr_count, m_ar, ar_mbm, ar_addr, m_regs[R_ER]));
|
||||
if (ar_mbm >= m_data_size || blr_nfc != 2)
|
||||
{
|
||||
command_fail_start(bi);
|
||||
}
|
||||
else
|
||||
{
|
||||
read_data_start(bi);
|
||||
}
|
||||
break;
|
||||
|
||||
case C_WRITE:
|
||||
DBG_LOG(1, "BMC", ("WBD: BLR %04x (NFC %d pages %d) AR %04x (MBM %d addr %03x) ER %02d\n",
|
||||
m_blr, blr_nfc, blr_count, m_ar, ar_mbm, ar_addr, m_regs[R_ER]));
|
||||
if (ar_mbm >= m_data_size || blr_nfc != 2)
|
||||
{
|
||||
command_fail_start(bi);
|
||||
}
|
||||
else
|
||||
{
|
||||
write_data_start(bi);
|
||||
}
|
||||
break;
|
||||
|
||||
// XXX clears all BMC registers (except BLR &c), counters and the MBM address RAM. used by Initialize as subroutine.
|
||||
case C_MBM_PURGE:
|
||||
m_regs[R_AR_L] = 0;
|
||||
m_regs[R_AR_M] &= ~7;
|
||||
update_regs();
|
||||
main_phase = PHASE_RESULT;
|
||||
m_str |= SR_DONE;
|
||||
break;
|
||||
|
||||
// controlled termination of currently executing command. command accepted in BUSY state.
|
||||
// if not BUSY, clears FIFO.
|
||||
case C_ABORT:
|
||||
if (main_phase == PHASE_IDLE)
|
||||
{
|
||||
fifo_clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
main_phase = PHASE_RESULT;
|
||||
bi.main_state = bi.sub_state = IDLE;
|
||||
}
|
||||
m_str |= SR_DONE;
|
||||
break;
|
||||
|
||||
case C_RESET_FIFO:
|
||||
fifo_clear();
|
||||
main_phase = PHASE_RESULT;
|
||||
m_str |= SR_DONE;
|
||||
break;
|
||||
|
||||
// clears BMC FIFO and all registers except those containing init parameters. sends Reset to every FSA.
|
||||
case C_RESET:
|
||||
m_regs[R_UR] = 0;
|
||||
fifo_clear();
|
||||
main_phase = PHASE_RESULT;
|
||||
m_str |= SR_DONE;
|
||||
break;
|
||||
|
||||
default:
|
||||
command_fail_start(bi);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void i7220_device::general_continue(bubble_info &bi)
|
||||
{
|
||||
switch (bi.main_state)
|
||||
{
|
||||
case IDLE:
|
||||
break;
|
||||
|
||||
case INIT:
|
||||
init_continue(bi);
|
||||
break;
|
||||
|
||||
case FAIL:
|
||||
command_fail_continue(bi);
|
||||
break;
|
||||
|
||||
case READ_FSA:
|
||||
read_fsa_continue(bi);
|
||||
break;
|
||||
|
||||
case READ_DATA:
|
||||
read_data_continue(bi);
|
||||
break;
|
||||
|
||||
case WRITE_DATA:
|
||||
write_data_continue(bi);
|
||||
break;
|
||||
|
||||
default:
|
||||
DBG_LOG(1,"BMC",("general_continue on unknown main-state %d\n", bi.main_state));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void i7220_device::delay_cycles(emu_timer *tm, int cycles)
|
||||
{
|
||||
tm->adjust(attotime::from_double(double(cycles) / clock()));
|
||||
}
|
||||
|
||||
void i7220_device::command_end(bubble_info &bi, bool success)
|
||||
{
|
||||
logerror("command done (%s) - %02x\n", success ? "success" : "fail", m_str);
|
||||
main_phase = PHASE_RESULT;
|
||||
bi.main_state = bi.sub_state = IDLE;
|
||||
if (success)
|
||||
{
|
||||
m_str |= SR_DONE;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_str |= SR_FAIL | SR_TE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void i7220_device::command_fail_start(bubble_info &bi)
|
||||
{
|
||||
bi.main_state = FAIL;
|
||||
bi.sub_state = INITIALIZE;
|
||||
|
||||
command_fail_continue(bi);
|
||||
}
|
||||
|
||||
void i7220_device::command_fail_continue(bubble_info &bi)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
switch (bi.sub_state)
|
||||
{
|
||||
case INITIALIZE:
|
||||
bi.sub_state = COMMAND_DONE;
|
||||
delay_cycles(bi.tm, 1200); // XXX
|
||||
return;
|
||||
|
||||
case COMMAND_DONE:
|
||||
command_end(bi, false);
|
||||
return;
|
||||
|
||||
default:
|
||||
DBG_LOG(1,"BMC",("fail unknown sub-state %d\n", bi.sub_state));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void i7220_device::init_start(bubble_info &bi)
|
||||
{
|
||||
bi.main_state = INIT;
|
||||
bi.sub_state = INITIALIZE;
|
||||
|
||||
init_continue(bi);
|
||||
}
|
||||
|
||||
void i7220_device::init_continue(bubble_info &bi)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
switch (bi.sub_state)
|
||||
{
|
||||
case INITIALIZE:
|
||||
bi.sub_state = WAIT_FSA_REPLY;
|
||||
delay_cycles(bi.tm, m_data_size * 60); // p. 4-16 of BPK72UM
|
||||
return;
|
||||
|
||||
case WAIT_FSA_REPLY:
|
||||
bi.sub_state = COMMAND_DONE;
|
||||
break;
|
||||
|
||||
case COMMAND_DONE:
|
||||
command_end(bi, true);
|
||||
return;
|
||||
|
||||
default:
|
||||
DBG_LOG(1,"BMC",("init unknown sub-state %d\n", bi.sub_state));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void i7220_device::read_fsa_start(bubble_info &bi)
|
||||
{
|
||||
bi.main_state = READ_FSA;
|
||||
bi.sub_state = INITIALIZE;
|
||||
|
||||
read_fsa_continue(bi);
|
||||
}
|
||||
|
||||
void i7220_device::read_fsa_continue(bubble_info &bi)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
switch (bi.sub_state)
|
||||
{
|
||||
case INITIALIZE:
|
||||
bi.sub_state = WAIT_FSA_REPLY;
|
||||
delay_cycles(bi.tm, m_data_size * 60); // p. 4-16 of BPK72UM
|
||||
return;
|
||||
|
||||
case WAIT_FSA_REPLY:
|
||||
bi.sub_state = COMMAND_DONE;
|
||||
break;
|
||||
|
||||
case COMMAND_DONE:
|
||||
// each bubble memory module has two FSA channels
|
||||
for (int a = 0; a < m_data_size; a++)
|
||||
{
|
||||
fifo_push(0x28); // FIFOMT | ECF/F
|
||||
fifo_push(0x28);
|
||||
}
|
||||
command_end(bi, true);
|
||||
return;
|
||||
|
||||
default:
|
||||
DBG_LOG(1,"BMC",("read fsa unknown sub-state %d\n", bi.sub_state));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void i7220_device::read_data_start(bubble_info &bi)
|
||||
{
|
||||
bi.main_state = READ_DATA;
|
||||
bi.sub_state = INITIALIZE;
|
||||
|
||||
read_data_continue(bi);
|
||||
}
|
||||
|
||||
void i7220_device::read_data_continue(bubble_info &bi)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
switch (bi.sub_state)
|
||||
{
|
||||
case INITIALIZE:
|
||||
bi.sub_state = SECTOR_READ;
|
||||
bi.counter = 0; // 256-bit pages
|
||||
bi.limit = blr_count * blr_nfc;
|
||||
fseek((ar_addr * 32 * blr_nfc) + (ar_mbm * I7110_MBM_SIZE) + (bi.counter * 32), SEEK_SET);
|
||||
break;
|
||||
|
||||
case SECTOR_READ:
|
||||
fread(buf, 32);
|
||||
bi.sub_state = WAIT_FSA_REPLY;
|
||||
delay_cycles(bi.tm, 270 * 20); // p. 4-14 of BPK72UM
|
||||
break;
|
||||
|
||||
case WAIT_FSA_REPLY:
|
||||
DBG_LOG(3,"BMC",("read data: ct %02d limit %02d\n", bi.counter, bi.limit));
|
||||
if (bi.counter < bi.limit)
|
||||
{
|
||||
for (int a = 0; a < 32; a++)
|
||||
fifo_push(buf[a]);
|
||||
bi.sub_state = SECTOR_READ;
|
||||
bi.counter++;
|
||||
delay_cycles(bi.tm, 270 * 20); // p. 4-14 of BPK72UM
|
||||
return;
|
||||
}
|
||||
bi.sub_state = COMMAND_DONE;
|
||||
break;
|
||||
|
||||
case COMMAND_DONE:
|
||||
command_end(bi, true);
|
||||
return;
|
||||
|
||||
default:
|
||||
DBG_LOG(1,"BMC",("read data unknown sub-state %d\n", bi.sub_state));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void i7220_device::write_data_start(bubble_info &bi)
|
||||
{
|
||||
bi.main_state = WRITE_DATA;
|
||||
bi.sub_state = INITIALIZE;
|
||||
|
||||
write_data_continue(bi);
|
||||
}
|
||||
|
||||
void i7220_device::write_data_continue(bubble_info &bi)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
switch (bi.sub_state)
|
||||
{
|
||||
case INITIALIZE:
|
||||
bi.sub_state = WAIT_FIFO;
|
||||
bi.counter = 0;
|
||||
bi.limit = blr_count * blr_nfc * 32;
|
||||
delay_cycles(bi.tm, 270 * 20); // p. 4-14 of BPK72UM
|
||||
return;
|
||||
|
||||
case WAIT_FIFO:
|
||||
DBG_LOG(3,"BMC",("write data: fifo %02d ct %02d limit %02d\n", m_fifo_size, bi.counter, bi.limit));
|
||||
if (m_fifo_size >= 32)
|
||||
{
|
||||
for (int a = 0; a < 32; a++)
|
||||
buf[a] = fifo_pop();
|
||||
fseek((ar_addr * 32 * blr_nfc) + (ar_mbm * I7110_MBM_SIZE) + bi.counter, SEEK_SET);
|
||||
fwrite(buf, 32);
|
||||
bi.counter += 32;
|
||||
}
|
||||
if (bi.counter < bi.limit)
|
||||
{
|
||||
delay_cycles(bi.tm, 270 * 20); // p. 4-14 of BPK72UM
|
||||
return;
|
||||
}
|
||||
bi.sub_state = COMMAND_DONE;
|
||||
break;
|
||||
|
||||
case COMMAND_DONE:
|
||||
command_end(bi, true);
|
||||
return;
|
||||
|
||||
default:
|
||||
DBG_LOG(1,"BMC",("write data unknown sub-state %d\n", bi.sub_state));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// read -
|
||||
//-------------------------------------------------
|
||||
|
||||
READ8_MEMBER(i7220_device::read)
|
||||
{
|
||||
uint8_t data = 0;
|
||||
|
||||
switch (offset & 1)
|
||||
{
|
||||
case 0:
|
||||
if (m_rac)
|
||||
{
|
||||
data = m_regs[m_rac];
|
||||
DBG_LOG(2, "BMC", ("R reg @ %02x == %02x\n", m_rac, data));
|
||||
m_rac++;
|
||||
m_rac &= 15;
|
||||
}
|
||||
else
|
||||
{
|
||||
data = fifo_pop();
|
||||
DBG_LOG(2, "BMC", ("R fifo == %02x\n", data));
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
data = m_str;
|
||||
if (main_phase == PHASE_EXEC)
|
||||
{
|
||||
data |= SR_BUSY;
|
||||
switch (bi.main_state)
|
||||
{
|
||||
case READ_DATA:
|
||||
if (!m_fifo.empty()) // XXX
|
||||
{
|
||||
data |= SR_FIFO;
|
||||
}
|
||||
break;
|
||||
|
||||
case WRITE_DATA:
|
||||
if (!m_fifo.full()) // XXX
|
||||
{
|
||||
data |= SR_FIFO;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!m_fifo.empty())
|
||||
{
|
||||
data |= SR_FIFO;
|
||||
}
|
||||
}
|
||||
DBG_LOG(2, "BMC", ("R status == %02x (phase %d state %d:%d fifo %d drq %d)\n",
|
||||
data, main_phase, bi.main_state, bi.sub_state, m_fifo_size, drq));
|
||||
if (main_phase == PHASE_RESULT)
|
||||
{
|
||||
main_phase = PHASE_IDLE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
DBG_LOG(3, "BMC", ("R @ %d == %02x\n", offset, data));
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// write -
|
||||
//-------------------------------------------------
|
||||
|
||||
WRITE8_MEMBER( i7220_device::write )
|
||||
{
|
||||
static const char *commands[] = {
|
||||
"Write Bootloop Register Masked",
|
||||
"Initialize",
|
||||
"Read Bubble Data",
|
||||
"Write Bubble Data",
|
||||
"Read Seek",
|
||||
"Read Bootloop Register",
|
||||
"Write Bootloop Register",
|
||||
"Write Bootloop",
|
||||
"Read FSA Status",
|
||||
"Abort",
|
||||
"Write Seek",
|
||||
"Read Bootloop",
|
||||
"Read Corrected Data",
|
||||
"Reset FIFO",
|
||||
"MBM Purge",
|
||||
"Software Reset"
|
||||
};
|
||||
|
||||
DBG_LOG(3, "BMC", ("W @ %d <- %02x\n", offset, data));
|
||||
|
||||
switch (offset & 1)
|
||||
{
|
||||
case 0:
|
||||
if (m_rac)
|
||||
{
|
||||
DBG_LOG(2, "BMC", ("W reg @ %02x <- %02x\n", m_rac, data));
|
||||
m_regs[m_rac] = data;
|
||||
update_regs();
|
||||
m_rac++;
|
||||
m_rac &= 15;
|
||||
}
|
||||
else
|
||||
{
|
||||
DBG_LOG(2, "BMC", ("W fifo <- %02x\n", data));
|
||||
fifo_push(data);
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
if (BIT(data, 5))
|
||||
{
|
||||
intrq_cb(CLEAR_LINE);
|
||||
}
|
||||
else if (BIT(data, 4))
|
||||
{
|
||||
m_cmdr = data & 15;
|
||||
if (main_phase == PHASE_IDLE)
|
||||
{
|
||||
DBG_LOG(1, "BMC", ("command %02x '%s'\n", data, commands[m_cmdr]));
|
||||
main_phase = PHASE_CMD;
|
||||
start_command(m_cmdr);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_rac = data & 15;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
240
src/devices/machine/i7220.h
Normal file
240
src/devices/machine/i7220.h
Normal file
@ -0,0 +1,240 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Sergey Svishchev
|
||||
/**********************************************************************
|
||||
|
||||
Intel 7220 Bubble Memory Controller emulation
|
||||
|
||||
**********************************************************************
|
||||
_____ _____
|
||||
/PWR.FAIL 1 |* \_/ | 40 Vcc
|
||||
/RESET.OUT 2 | | 39 /X+
|
||||
CLK 3 | | 38 /X-
|
||||
/RESET 4 | | 37 /Y+
|
||||
/RD 5 | | 36 /Y-
|
||||
/WR 6 | | 35 /TM.A
|
||||
/DACK 7 | | 34 /TM.B
|
||||
DRQ 8 | | 33 /REP.EN
|
||||
INT 9 | | 32 /BOOT.EN
|
||||
A0 10 | 7220 | 31 /SWAP.EN
|
||||
D0 11 | | 30 /BOOT.S.EN
|
||||
D1 12 | | 29 C/D
|
||||
D2 13 | | 28 /DET.ON
|
||||
D3 14 | | 27 /ERR.FLG
|
||||
D4 15 | | 26 /WAIT
|
||||
D5 16 | | 25 /BUS.RD
|
||||
D6 17 | | 24 /SHIFT.CLK
|
||||
D7 18 | | 23 /SYNC
|
||||
D8 19 | | 22 DIO
|
||||
GND 20 |_____________| 21 /CS
|
||||
|
||||
**********************************************************************/
|
||||
|
||||
#ifndef MAME_MACHINE_I7220_H
|
||||
#define MAME_MACHINE_I7220_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#define I7110_MBM_SIZE (128 * 1024) // 1 megabit
|
||||
#define I7115_MBM_SIZE (512 * 1024) // 4 megabit
|
||||
|
||||
|
||||
///*************************************************************************
|
||||
// INTERFACE CONFIGURATION MACROS
|
||||
///*************************************************************************
|
||||
|
||||
#define MCFG_I7220_IRQ_CALLBACK(_write) \
|
||||
devcb = &i7220_device::set_intrq_wr_callback(*device, DEVCB_##_write);
|
||||
|
||||
#define MCFG_I7220_DRQ_CALLBACK(_write) \
|
||||
devcb = &i7220_device::set_drq_wr_callback(*device, DEVCB_##_write);
|
||||
|
||||
#define MCFG_I7220_DATA_SIZE(data_size) \
|
||||
i7220_device::set_data_size(*device, data_size);
|
||||
|
||||
|
||||
|
||||
///*************************************************************************
|
||||
// TYPE DEFINITIONS
|
||||
///*************************************************************************
|
||||
|
||||
// ======================> i7220_device
|
||||
|
||||
class i7220_device : public device_t,
|
||||
public device_image_interface
|
||||
{
|
||||
public:
|
||||
// construction/destruction
|
||||
i7220_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||
|
||||
template <class Object> static devcb_base &set_intrq_wr_callback(device_t &device, Object &&cb) { return downcast<i7220_device &>(device).intrq_cb.set_callback(std::forward<Object>(cb)); }
|
||||
template <class Object> static devcb_base &set_drq_wr_callback(device_t &device, Object &&cb) { return downcast<i7220_device &>(device).drq_cb.set_callback(std::forward<Object>(cb)); }
|
||||
|
||||
static void set_data_size(device_t &device, int data_size) { downcast<i7220_device &>(device).m_data_size = data_size; }
|
||||
|
||||
// image-level overrides
|
||||
virtual image_init_result call_load() override;
|
||||
|
||||
virtual iodevice_t image_type() const override { return IO_MEMCARD; }
|
||||
|
||||
virtual bool is_readable() const override { return 1; }
|
||||
virtual bool is_writeable() const override { return 1; }
|
||||
virtual bool is_creatable() const override { return 0; }
|
||||
virtual bool must_be_loaded() const override { return 1; }
|
||||
virtual bool is_reset_on_load() const override { return 0; }
|
||||
virtual const char *file_extensions() const override { return "bubble"; }
|
||||
|
||||
DECLARE_READ8_MEMBER(read);
|
||||
DECLARE_WRITE8_MEMBER(write);
|
||||
|
||||
protected:
|
||||
// device-level overrides
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
|
||||
|
||||
int m_data_size;
|
||||
|
||||
private:
|
||||
enum {
|
||||
PHASE_IDLE, PHASE_CMD, PHASE_EXEC, PHASE_RESULT
|
||||
};
|
||||
|
||||
enum {
|
||||
// General "doing nothing" state
|
||||
IDLE,
|
||||
|
||||
// Main states
|
||||
INIT,
|
||||
READ_FSA,
|
||||
READ_DATA,
|
||||
WRITE_DATA,
|
||||
FAIL,
|
||||
|
||||
// Sub-states
|
||||
INITIALIZE,
|
||||
|
||||
WAIT_FSA_REPLY,
|
||||
WAIT_FSA_REPLY_DONE,
|
||||
|
||||
WAIT_FIFO,
|
||||
WAIT_FIFO_DONE,
|
||||
|
||||
COMMAND_DONE,
|
||||
|
||||
SECTOR_READ,
|
||||
SECTOR_WRITTEN
|
||||
};
|
||||
|
||||
enum {
|
||||
C_WRITE_BOOTLOOP_REG_MASKED,
|
||||
C_INIT,
|
||||
C_READ,
|
||||
C_WRITE,
|
||||
C_READ_SEEK,
|
||||
C_READ_BOOTLOOP_REG,
|
||||
C_WRITE_BOOTLOOP_REG,
|
||||
C_WRITE_BOOTLOOP,
|
||||
C_READ_FSA_STATUS,
|
||||
C_ABORT,
|
||||
C_WRITE_SEEK,
|
||||
C_READ_BOOTLOOP,
|
||||
C_READ_CORRECTED,
|
||||
C_RESET_FIFO,
|
||||
C_MBM_PURGE,
|
||||
C_RESET
|
||||
};
|
||||
|
||||
enum {
|
||||
R_UR = 0x0a,
|
||||
R_BLR_L = 0x0b,
|
||||
R_BLR_M = 0x0c,
|
||||
R_ER = 0x0d,
|
||||
R_AR_L = 0x0e,
|
||||
R_AR_M = 0x0f,
|
||||
};
|
||||
|
||||
enum {
|
||||
ER_IEN = 0x01,
|
||||
ER_IEE = 0x02,
|
||||
ER_DMAEN = 0x04,
|
||||
ER_MFBTR = 0x08,
|
||||
ER_WBE = 0x10,
|
||||
ER_ERCD = 0x20,
|
||||
ER_EICD = 0x40,
|
||||
ER_EPI = 0x80
|
||||
};
|
||||
|
||||
enum {
|
||||
SR_FIFO = 0x01,
|
||||
SR_PE = 0x02,
|
||||
SR_UE = 0x04,
|
||||
SR_CE = 0x08,
|
||||
SR_TE = 0x10,
|
||||
SR_FAIL = 0x20,
|
||||
SR_DONE = 0x40,
|
||||
SR_BUSY = 0x80,
|
||||
|
||||
SR_CLEAR = 0x7E
|
||||
};
|
||||
|
||||
struct bubble_info {
|
||||
emu_timer *tm;
|
||||
int main_state, sub_state;
|
||||
int limit, counter;
|
||||
};
|
||||
|
||||
void delay_cycles(emu_timer *tm, int cycles);
|
||||
void set_drq(bool state);
|
||||
void set_irq(bool state);
|
||||
|
||||
void update_regs();
|
||||
void update_drq();
|
||||
|
||||
void start_command(int cmd);
|
||||
void general_continue(bubble_info &bi);
|
||||
void command_end(bubble_info &bi, bool success);
|
||||
|
||||
void command_fail_start(bubble_info &bi);
|
||||
void command_fail_continue(bubble_info &bi);
|
||||
|
||||
void init_start(bubble_info &bi);
|
||||
void init_continue(bubble_info &bi);
|
||||
|
||||
void read_fsa_start(bubble_info &bi);
|
||||
void read_fsa_continue(bubble_info &bi);
|
||||
|
||||
void read_data_start(bubble_info &bi);
|
||||
void read_data_continue(bubble_info &bi);
|
||||
|
||||
void write_data_start(bubble_info &bi);
|
||||
void write_data_continue(bubble_info &bi);
|
||||
|
||||
void fifo_clear();
|
||||
void fifo_push(uint8_t val);
|
||||
uint8_t fifo_pop();
|
||||
|
||||
int main_phase;
|
||||
bool drq, irq;
|
||||
bubble_info bi;
|
||||
|
||||
uint8_t buf[32];
|
||||
int blr_count, blr_nfc, ar_addr, ar_mbm;
|
||||
|
||||
devcb_write_line intrq_cb;
|
||||
devcb_write_line drq_cb;
|
||||
|
||||
uint8_t m_regs[16];
|
||||
uint8_t m_rac;
|
||||
uint8_t m_cmdr;
|
||||
uint8_t m_str;
|
||||
uint16_t m_blr;
|
||||
uint16_t m_ar;
|
||||
int m_fifo_size;
|
||||
util::fifo<uint8_t, 40> m_fifo;
|
||||
};
|
||||
|
||||
|
||||
// device type definition
|
||||
DECLARE_DEVICE_TYPE(I7220, i7220_device)
|
||||
|
||||
#endif // MAME_MACHINE_I7220_H
|
@ -71,6 +71,7 @@ enum
|
||||
XTAL_3_6864MHz = 3686400, /* Baud rate clock for MC68681 and similar UARTs */
|
||||
XTAL_4MHz = 4000000,
|
||||
XTAL_4_028MHz = 4028000, /* Sony SMC-777 */
|
||||
XTAL_4_032MHz = 4032000, /* GRiD Compass modem board */
|
||||
XTAL_4_096MHz = 4096000, /* Used to drive OKI M9810 chips */
|
||||
XTAL_4_194304Mhz = 4194304, /* Used to drive MC146818 / Nintendo Game Boy */
|
||||
XTAL_4_224MHz = 4224000, /* Used to drive OKI M6295 chips, usually with /4 divider */
|
||||
|
586
src/mame/drivers/gridcomp.cpp
Normal file
586
src/mame/drivers/gridcomp.cpp
Normal file
@ -0,0 +1,586 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Sergey Svishchev
|
||||
/***************************************************************************
|
||||
|
||||
drivers/gridcomp.cpp
|
||||
|
||||
Driver file for GRiD Compass series
|
||||
|
||||
US patent 4,571,456 describes model 1101:
|
||||
|
||||
- 15 MHz XTAL, produces
|
||||
- 5 MHz system clock for CPU, FPU, OSP
|
||||
- 7.5 MHz pixel clock
|
||||
- Intel 8086 - CPU
|
||||
- Intel 8087 - FPU
|
||||
- Intel 80130 - Operating System Processor, equivalent of:
|
||||
- 8259 PIC
|
||||
- 8254 PIT
|
||||
- Texas Instruments TMS9914 GPIB controller
|
||||
- Intel 7220 Bubble Memory Controller
|
||||
- 7110 Magnetic Bubble Memory modules and support chips
|
||||
- (unknown) - EAROM for machine ID
|
||||
- (unknown) - Real-Time Clock
|
||||
- (custom DMA logic)
|
||||
- Intel 8741 - keyboard MCU
|
||||
- Intel 8274 - UART
|
||||
- Intel 8255 - modem interface
|
||||
- 2x DAC0832LCN - DAC
|
||||
- MK5089N - DTMF generator
|
||||
- ...
|
||||
|
||||
to do:
|
||||
|
||||
- confirm differences between models except screen size
|
||||
- Compass 110x do not have GRiDROM slots.
|
||||
- Compass II (112x, 113x) have 4 of them.
|
||||
- keyboard: decode and add the rest of keycodes
|
||||
- EAROM, RTC
|
||||
- serial port, modem (incl. DTMF generator)
|
||||
- TMS9914 chip driver (incl. DMA)
|
||||
- GPIB storage devices (floppy, hard disk)
|
||||
|
||||
missing dumps:
|
||||
|
||||
- BIOS from models other than 1139 (CCOS and MS-DOS variants)
|
||||
- GRiDROM's
|
||||
- keyboard MCU
|
||||
- external floppy and hard disk (2101, 2102)
|
||||
|
||||
to boot CCOS 3.0.1:
|
||||
- pad binary image (not .imd) to 384K
|
||||
- attach it as -memcard
|
||||
- use grid1129 with 'patched' ROM
|
||||
- start with -debug and add breakpoints:
|
||||
|
||||
# bubble memory driver
|
||||
bp ff27a,1,{ax=ax*2;go}
|
||||
# boot loader
|
||||
bp 20618,1,{temp0=214A8;do w@(temp0+7)=120;do w@(temp0+9)=121;go}
|
||||
# CCOS kernel
|
||||
bp 0661a,1,{temp0=0f964;do w@(temp0+7)=120;do w@(temp0+9)=121;go}
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
|
||||
#include "bus/rs232/rs232.h"
|
||||
#include "cpu/i86/i86.h"
|
||||
#include "machine/gridkeyb.h"
|
||||
#include "machine/i7220.h"
|
||||
#include "machine/i80130.h"
|
||||
#include "machine/i8255.h"
|
||||
#include "machine/ram.h"
|
||||
#include "machine/z80sio.h"
|
||||
#include "sound/spkrdev.h"
|
||||
|
||||
#include "rendlay.h"
|
||||
#include "screen.h"
|
||||
#include "softlist.h"
|
||||
#include "speaker.h"
|
||||
|
||||
|
||||
#define VERBOSE_DBG 1
|
||||
|
||||
#define DBG_LOG(N,M,A) \
|
||||
do { \
|
||||
if(VERBOSE_DBG>=N) \
|
||||
{ \
|
||||
if( M ) \
|
||||
logerror("%11.6f at %s: %-10s",machine().time().as_double(),machine().describe_context(),(char*)M ); \
|
||||
logerror A; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
||||
#define I80130_TAG "osp"
|
||||
|
||||
class gridcomp_state : public driver_device
|
||||
{
|
||||
public:
|
||||
gridcomp_state(const machine_config &mconfig, device_type type, const char *tag)
|
||||
: driver_device(mconfig, type, tag)
|
||||
, m_maincpu(*this, "maincpu")
|
||||
, m_osp(*this, I80130_TAG)
|
||||
, m_modem(*this, "modem")
|
||||
, m_uart8274(*this, "uart8274")
|
||||
, m_speaker(*this, "speaker")
|
||||
, m_ram(*this, RAM_TAG)
|
||||
{ }
|
||||
|
||||
required_device<cpu_device> m_maincpu;
|
||||
required_device<i80130_device> m_osp;
|
||||
required_device<i8255_device> m_modem;
|
||||
optional_device<i8274_new_device> m_uart8274;
|
||||
required_device<speaker_sound_device> m_speaker;
|
||||
required_device<ram_device> m_ram;
|
||||
|
||||
DECLARE_DRIVER_INIT(gridcomp);
|
||||
DECLARE_MACHINE_START(gridcomp);
|
||||
DECLARE_MACHINE_RESET(gridcomp);
|
||||
|
||||
IRQ_CALLBACK_MEMBER(irq_callback);
|
||||
|
||||
DECLARE_READ16_MEMBER(grid_9ff0_r);
|
||||
DECLARE_READ16_MEMBER(grid_keyb_r);
|
||||
DECLARE_READ16_MEMBER(grid_gpib_r);
|
||||
DECLARE_WRITE16_MEMBER(grid_keyb_w);
|
||||
DECLARE_WRITE16_MEMBER(grid_gpib_w);
|
||||
|
||||
uint32_t screen_update_110x(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
|
||||
uint32_t screen_update_113x(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
|
||||
uint32_t screen_update_generic(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int px);
|
||||
|
||||
void kbd_put(u16 data);
|
||||
|
||||
private:
|
||||
bool m_kbd_ready;
|
||||
uint16_t m_kbd_data;
|
||||
|
||||
uint16_t *m_videoram;
|
||||
};
|
||||
|
||||
|
||||
READ16_MEMBER(gridcomp_state::grid_9ff0_r)
|
||||
{
|
||||
uint16_t data = 0;
|
||||
|
||||
switch (offset)
|
||||
{
|
||||
case 0:
|
||||
data = 0xbb66;
|
||||
break;
|
||||
}
|
||||
|
||||
DBG_LOG(1, "9FF0", ("%02x == %02x\n", 0x9ff00 + (offset << 1), data));
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
READ16_MEMBER(gridcomp_state::grid_keyb_r)
|
||||
{
|
||||
uint16_t data = 0;
|
||||
|
||||
switch (offset)
|
||||
{
|
||||
case 0:
|
||||
data = m_kbd_data;
|
||||
m_kbd_data = 0xff;
|
||||
m_kbd_ready = false;
|
||||
m_osp->ir4_w(CLEAR_LINE);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
data = m_kbd_ready ? 2 : 0;
|
||||
break;
|
||||
}
|
||||
|
||||
DBG_LOG(1, "Keyb", ("%02x == %02x\n", 0xdffc0 + (offset << 1), data));
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
WRITE16_MEMBER(gridcomp_state::grid_keyb_w)
|
||||
{
|
||||
DBG_LOG(1, "Keyb", ("%02x <- %02x\n", 0xdffc0 + (offset << 1), data));
|
||||
}
|
||||
|
||||
void gridcomp_state::kbd_put(u16 data)
|
||||
{
|
||||
m_kbd_data = data;
|
||||
m_kbd_ready = true;
|
||||
m_osp->ir4_w(ASSERT_LINE);
|
||||
}
|
||||
|
||||
|
||||
// reject all commands
|
||||
READ16_MEMBER(gridcomp_state::grid_gpib_r)
|
||||
{
|
||||
uint16_t data = 0;
|
||||
|
||||
switch (offset)
|
||||
{
|
||||
case 0:
|
||||
data = 0x10; // BO
|
||||
break;
|
||||
|
||||
case 1:
|
||||
data = 0x40; // ERR
|
||||
m_osp->ir5_w(CLEAR_LINE);
|
||||
break;
|
||||
}
|
||||
|
||||
DBG_LOG(1, "GPIB", ("%02x == %02x\n", 0xdff80 + (offset << 1), data));
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
WRITE16_MEMBER(gridcomp_state::grid_gpib_w)
|
||||
{
|
||||
switch (offset)
|
||||
{
|
||||
case 7:
|
||||
m_osp->ir5_w(ASSERT_LINE);
|
||||
break;
|
||||
}
|
||||
|
||||
DBG_LOG(1, "GPIB", ("%02x <- %02x\n", 0xdff80 + (offset << 1), data));
|
||||
}
|
||||
|
||||
|
||||
uint32_t gridcomp_state::screen_update_generic(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int px)
|
||||
{
|
||||
int x, y, offset;
|
||||
uint16_t gfx, *p;
|
||||
|
||||
for (y = 0; y < 240; y++)
|
||||
{
|
||||
p = &bitmap.pix16(y);
|
||||
|
||||
offset = y * (px / 16);
|
||||
|
||||
for (x = offset; x < offset + px / 16; x++)
|
||||
{
|
||||
gfx = m_videoram[x];
|
||||
|
||||
*p++ = BIT(gfx, 15);
|
||||
*p++ = BIT(gfx, 14);
|
||||
*p++ = BIT(gfx, 13);
|
||||
*p++ = BIT(gfx, 12);
|
||||
*p++ = BIT(gfx, 11);
|
||||
*p++ = BIT(gfx, 10);
|
||||
*p++ = BIT(gfx, 9);
|
||||
*p++ = BIT(gfx, 8);
|
||||
*p++ = BIT(gfx, 7);
|
||||
*p++ = BIT(gfx, 6);
|
||||
*p++ = BIT(gfx, 5);
|
||||
*p++ = BIT(gfx, 4);
|
||||
*p++ = BIT(gfx, 3);
|
||||
*p++ = BIT(gfx, 2);
|
||||
*p++ = BIT(gfx, 1);
|
||||
*p++ = BIT(gfx, 0);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t gridcomp_state::screen_update_110x(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
|
||||
{
|
||||
return screen_update_generic(screen, bitmap, cliprect, 320);
|
||||
}
|
||||
|
||||
uint32_t gridcomp_state::screen_update_113x(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
|
||||
{
|
||||
return screen_update_generic(screen, bitmap, cliprect, 512);
|
||||
}
|
||||
|
||||
|
||||
DRIVER_INIT_MEMBER(gridcomp_state, gridcomp)
|
||||
{
|
||||
DBG_LOG(0, "init", ("driver_init()\n"));
|
||||
}
|
||||
|
||||
MACHINE_START_MEMBER(gridcomp_state, gridcomp)
|
||||
{
|
||||
address_space &program = m_maincpu->space(AS_PROGRAM);
|
||||
|
||||
DBG_LOG(0, "init", ("machine_start()\n"));
|
||||
|
||||
program.install_readwrite_bank(0, m_ram->size() - 1, "bank10");
|
||||
membank("bank10")->set_base(m_ram->pointer());
|
||||
|
||||
m_videoram = (uint16_t *)m_maincpu->space(AS_PROGRAM).get_write_ptr(0x400);
|
||||
}
|
||||
|
||||
MACHINE_RESET_MEMBER(gridcomp_state, gridcomp)
|
||||
{
|
||||
DBG_LOG(0, "init", ("machine_reset()\n"));
|
||||
|
||||
m_kbd_ready = false;
|
||||
}
|
||||
|
||||
IRQ_CALLBACK_MEMBER(gridcomp_state::irq_callback)
|
||||
{
|
||||
return m_osp->inta_r();
|
||||
}
|
||||
|
||||
|
||||
static ADDRESS_MAP_START( grid1101_map, AS_PROGRAM, 16, gridcomp_state )
|
||||
ADDRESS_MAP_UNMAP_HIGH
|
||||
AM_RANGE(0xdfe80, 0xdfe83) AM_DEVREADWRITE8("i7220", i7220_device, read, write, 0x00ff)
|
||||
AM_RANGE(0xdfea0, 0xdfeaf) AM_UNMAP // ??
|
||||
AM_RANGE(0xdfec0, 0xdfecf) AM_DEVREADWRITE8("modem", i8255_device, read, write, 0x00ff) // incl. DTMF generator
|
||||
AM_RANGE(0xdff40, 0xdff5f) AM_NOP // ?? machine ID EAROM, RTC
|
||||
AM_RANGE(0xdff80, 0xdff8f) AM_READWRITE(grid_gpib_r, grid_gpib_w) // TMS9914
|
||||
AM_RANGE(0xdffc0, 0xdffcf) AM_READWRITE(grid_keyb_r, grid_keyb_w) // Intel 8741 MCU
|
||||
AM_RANGE(0xfc000, 0xfffff) AM_ROM AM_REGION("user1", 0)
|
||||
ADDRESS_MAP_END
|
||||
|
||||
static ADDRESS_MAP_START( grid1121_map, AS_PROGRAM, 16, gridcomp_state )
|
||||
ADDRESS_MAP_UNMAP_HIGH
|
||||
AM_RANGE(0x90000, 0x97fff) AM_UNMAP // ?? ROM slot
|
||||
AM_RANGE(0x9ff00, 0x9ff0f) AM_UNMAP // AM_READ(grid_9ff0_r) // ?? ROM?
|
||||
AM_RANGE(0xc0000, 0xcffff) AM_UNMAP // ?? ROM slot -- signature expected: 0x4554, 0x5048
|
||||
AM_RANGE(0xdfe00, 0xdfe1f) AM_UNMAP // AM_DEVREADWRITE8("uart8274", i8274_new_device, ba_cd_r, ba_cd_w, 0x00ff)
|
||||
AM_RANGE(0xdfe40, 0xdfe4f) AM_UNMAP // ?? diagnostic 8274
|
||||
AM_RANGE(0xdfe80, 0xdfe83) AM_DEVREADWRITE8("i7220", i7220_device, read, write, 0x00ff)
|
||||
AM_RANGE(0xdfea0, 0xdfeaf) AM_UNMAP // ??
|
||||
AM_RANGE(0xdfec0, 0xdfecf) AM_DEVREADWRITE8("modem", i8255_device, read, write, 0x00ff) // incl. DTMF generator
|
||||
AM_RANGE(0xdff40, 0xdff5f) AM_NOP // ?? machine ID EAROM, RTC
|
||||
AM_RANGE(0xdff80, 0xdff8f) AM_READWRITE(grid_gpib_r, grid_gpib_w) // TMS9914
|
||||
AM_RANGE(0xdffc0, 0xdffcf) AM_READWRITE(grid_keyb_r, grid_keyb_w) // Intel 8741 MCU
|
||||
AM_RANGE(0xfc000, 0xfffff) AM_ROM AM_REGION("user1", 0)
|
||||
ADDRESS_MAP_END
|
||||
|
||||
static ADDRESS_MAP_START( grid1101_io, AS_IO, 16, gridcomp_state )
|
||||
AM_RANGE(0x0000, 0x000f) AM_DEVICE(I80130_TAG, i80130_device, io_map)
|
||||
ADDRESS_MAP_END
|
||||
|
||||
static INPUT_PORTS_START( gridcomp )
|
||||
INPUT_PORTS_END
|
||||
|
||||
/*
|
||||
* IRQ0 serial
|
||||
* IRQ1 bubble
|
||||
* IRQ2 modem
|
||||
* IRQ3 system tick || vert sync
|
||||
* IRQ4 keyboard
|
||||
* IRQ5 gpib
|
||||
* IRQ6 8087
|
||||
* IRQ7 ring
|
||||
*/
|
||||
static MACHINE_CONFIG_START( grid1101 )
|
||||
MCFG_CPU_ADD("maincpu", I8086, XTAL_15MHz / 3)
|
||||
MCFG_CPU_PROGRAM_MAP(grid1101_map)
|
||||
MCFG_CPU_IO_MAP(grid1101_io)
|
||||
MCFG_CPU_IRQ_ACKNOWLEDGE_DRIVER(gridcomp_state, irq_callback)
|
||||
|
||||
MCFG_MACHINE_START_OVERRIDE(gridcomp_state, gridcomp)
|
||||
MCFG_MACHINE_RESET_OVERRIDE(gridcomp_state, gridcomp)
|
||||
|
||||
MCFG_DEVICE_ADD(I80130_TAG, I80130, XTAL_15MHz/3)
|
||||
MCFG_I80130_IRQ_CALLBACK(INPUTLINE("maincpu", 0))
|
||||
|
||||
MCFG_SPEAKER_STANDARD_MONO("mono")
|
||||
MCFG_SOUND_ADD("speaker", SPEAKER_SOUND, 0)
|
||||
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.00)
|
||||
|
||||
MCFG_SCREEN_ADD_MONOCHROME("screen", RASTER, rgb_t::amber())
|
||||
MCFG_SCREEN_UPDATE_DRIVER(gridcomp_state, screen_update_110x)
|
||||
MCFG_SCREEN_RAW_PARAMS(XTAL_15MHz/2, 424, 0, 320, 262, 0, 240) // XXX 66 Hz refresh
|
||||
MCFG_SCREEN_VBLANK_CALLBACK(DEVWRITELINE(I80130_TAG, i80130_device, ir3_w))
|
||||
MCFG_DEFAULT_LAYOUT(layout_lcd)
|
||||
|
||||
MCFG_SCREEN_PALETTE("palette")
|
||||
MCFG_PALETTE_ADD_MONOCHROME("palette")
|
||||
|
||||
MCFG_DEVICE_ADD("keyboard", GRID_KEYBOARD, 0)
|
||||
MCFG_GRID_KEYBOARD_CB(PUT(gridcomp_state, kbd_put))
|
||||
|
||||
MCFG_DEVICE_ADD("i7220", I7220, XTAL_4MHz)
|
||||
MCFG_I7220_DATA_SIZE(3) // 3 1-Mbit MBM's
|
||||
MCFG_I7220_IRQ_CALLBACK(DEVWRITELINE(I80130_TAG, i80130_device, ir1_w))
|
||||
MCFG_I7220_DRQ_CALLBACK(DEVWRITELINE(I80130_TAG, i80130_device, ir1_w))
|
||||
|
||||
MCFG_I8274_ADD("uart8274", XTAL_4_032MHz, 0, 0, 0, 0)
|
||||
|
||||
MCFG_DEVICE_ADD("modem", I8255, 0)
|
||||
|
||||
MCFG_RAM_ADD(RAM_TAG)
|
||||
MCFG_RAM_DEFAULT_SIZE("256K")
|
||||
MCFG_RAM_DEFAULT_VALUE(0)
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
static MACHINE_CONFIG_DERIVED( grid1109, grid1101 )
|
||||
MCFG_DEVICE_MODIFY(RAM_TAG)
|
||||
MCFG_RAM_DEFAULT_SIZE("512K")
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
static MACHINE_CONFIG_DERIVED( grid1121, grid1101 )
|
||||
MCFG_CPU_MODIFY("maincpu")
|
||||
MCFG_CPU_CLOCK(XTAL_24MHz / 3) // XXX
|
||||
MCFG_CPU_PROGRAM_MAP(grid1121_map)
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
static MACHINE_CONFIG_DERIVED( grid1129, grid1121 )
|
||||
MCFG_DEVICE_MODIFY(RAM_TAG)
|
||||
MCFG_RAM_DEFAULT_SIZE("512K")
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
static MACHINE_CONFIG_DERIVED( grid1131, grid1121 )
|
||||
MCFG_SCREEN_MODIFY("screen")
|
||||
MCFG_SCREEN_UPDATE_DRIVER(gridcomp_state, screen_update_113x)
|
||||
MCFG_SCREEN_RAW_PARAMS(XTAL_15MHz/2, 720, 0, 512, 262, 0, 240) // XXX
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
static MACHINE_CONFIG_DERIVED( grid1139, grid1131 )
|
||||
MCFG_DEVICE_MODIFY(RAM_TAG)
|
||||
MCFG_RAM_DEFAULT_SIZE("512K")
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
|
||||
ROM_START( grid1101 )
|
||||
ROM_REGION16_LE(0x10000, "user1", 0)
|
||||
|
||||
ROM_SYSTEM_BIOS(0, "ccos", "ccos bios")
|
||||
ROMX_LOAD("1101EVEN.BIN", 0x0000, 0x2000, NO_DUMP, ROM_SKIP(1)|ROM_BIOS(1))
|
||||
ROMX_LOAD("1101ODD.BIN", 0x0001, 0x2000, NO_DUMP, ROM_SKIP(1)|ROM_BIOS(1))
|
||||
ROM_END
|
||||
|
||||
ROM_START( grid1109 )
|
||||
ROM_REGION16_LE(0x10000, "user1", 0)
|
||||
|
||||
ROM_SYSTEM_BIOS(0, "ccos", "ccos bios")
|
||||
ROMX_LOAD("1109EVEN.BIN", 0x0000, 0x2000, NO_DUMP, ROM_SKIP(1)|ROM_BIOS(1))
|
||||
ROMX_LOAD("1109ODD.BIN", 0x0001, 0x2000, NO_DUMP, ROM_SKIP(1)|ROM_BIOS(1))
|
||||
ROM_END
|
||||
|
||||
ROM_START( grid1121 )
|
||||
ROM_REGION16_LE(0x10000, "user1", 0)
|
||||
|
||||
ROM_SYSTEM_BIOS(0, "ccos", "ccos bios")
|
||||
ROMX_LOAD("1121EVEN.BIN", 0x0000, 0x2000, NO_DUMP, ROM_SKIP(1)|ROM_BIOS(1))
|
||||
ROMX_LOAD("1121ODD.BIN", 0x0001, 0x2000, NO_DUMP, ROM_SKIP(1)|ROM_BIOS(1))
|
||||
ROM_END
|
||||
|
||||
ROM_START( grid1129 )
|
||||
ROM_REGION16_LE(0x10000, "user1", 0)
|
||||
ROM_DEFAULT_BIOS("patched")
|
||||
|
||||
ROM_SYSTEM_BIOS(0, "ccos", "ccos bios")
|
||||
ROMX_LOAD("1129EVEN.BIN", 0x0000, 0x2000, NO_DUMP, ROM_SKIP(1)|ROM_BIOS(1))
|
||||
ROMX_LOAD("1129ODD.BIN", 0x0001, 0x2000, NO_DUMP, ROM_SKIP(1)|ROM_BIOS(1))
|
||||
|
||||
ROM_SYSTEM_BIOS(1, "patched", "patched 1139 bios")
|
||||
ROMX_LOAD("1139EVEN.BIN", 0x0000, 0x2000, CRC(67071849) SHA1(782239c155fa5821f8dbd2607cee9152d175e90e),ROM_SKIP(1)|ROM_BIOS(2))
|
||||
ROMX_LOAD("1139ODD.BIN", 0x0001, 0x2000, CRC(13ed4bf0) SHA1(f7087f86dbbc911bee985125bccd2417e0374e8e),ROM_SKIP(1)|ROM_BIOS(2))
|
||||
|
||||
// change bubble driver setup to read floppy images with 512-byte sectors
|
||||
ROM_FILL(0x3114,1,0x00)
|
||||
ROM_FILL(0x3115,1,0x02)
|
||||
ROM_FILL(0x3116,1,0xf8)
|
||||
ROM_FILL(0x3117,1,0x01)
|
||||
|
||||
// move work area from 0440h:XXXX to 0298h:XXXX
|
||||
ROM_FILL(0x23,1,0x98)
|
||||
ROM_FILL(0x24,1,0x2)
|
||||
ROM_FILL(0xbc,1,0x98)
|
||||
ROM_FILL(0xbd,1,0x2)
|
||||
ROM_FILL(0x14e,1,0xc1) //
|
||||
ROM_FILL(0x14f,1,0x2) //
|
||||
ROM_FILL(0x15a,1,0xc2) //
|
||||
ROM_FILL(0x15b,1,0x2) //
|
||||
ROM_FILL(0x17b,1,0x45) //
|
||||
ROM_FILL(0x17c,1,0x3) //
|
||||
ROM_FILL(0x28c,1,0x98)
|
||||
ROM_FILL(0x28d,1,0x2)
|
||||
ROM_FILL(0x28f,1,0x98)
|
||||
ROM_FILL(0x290,1,0x2)
|
||||
ROM_FILL(0x2b9,1,0x98)
|
||||
ROM_FILL(0x2ba,1,0x2)
|
||||
ROM_FILL(0x2d0,1,0x98)
|
||||
ROM_FILL(0x2d1,1,0x2)
|
||||
ROM_FILL(0x31a,1,0x98)
|
||||
ROM_FILL(0x31b,1,0x2)
|
||||
ROM_FILL(0x3a0,1,0x98)
|
||||
ROM_FILL(0x3a1,1,0x2)
|
||||
ROM_FILL(0x3a3,1,0x98)
|
||||
ROM_FILL(0x3a4,1,0x2)
|
||||
ROM_FILL(0x3e2,1,0x98)
|
||||
ROM_FILL(0x3e3,1,0x2)
|
||||
ROM_FILL(0x43e,1,0x98)
|
||||
ROM_FILL(0x43f,1,0x2)
|
||||
ROM_FILL(0x46d,1,0x98)
|
||||
ROM_FILL(0x46e,1,0x2)
|
||||
ROM_FILL(0x4fe,1,0x98)
|
||||
ROM_FILL(0x4ff,1,0x2)
|
||||
ROM_FILL(0x512,1,0x98)
|
||||
ROM_FILL(0x513,1,0x2)
|
||||
ROM_FILL(0x768,1,0x98)
|
||||
ROM_FILL(0x769,1,0x2)
|
||||
ROM_FILL(0x79e,1,0x98)
|
||||
ROM_FILL(0x79f,1,0x2)
|
||||
ROM_FILL(0x7f5,1,0x98)
|
||||
ROM_FILL(0x7f6,1,0x2)
|
||||
ROM_FILL(0x92a,1,0x98)
|
||||
ROM_FILL(0x92b,1,0x2)
|
||||
ROM_FILL(0xe50,1,0x98)
|
||||
ROM_FILL(0xe51,1,0x2)
|
||||
ROM_FILL(0xfa6,1,0x98)
|
||||
ROM_FILL(0xfa7,1,0x2)
|
||||
ROM_FILL(0x15fe,1,0xce) //
|
||||
ROM_FILL(0x15ff,1,0x2) //
|
||||
ROM_FILL(0x1628,1,0xd0) //
|
||||
ROM_FILL(0x1629,1,0x2) //
|
||||
ROM_FILL(0x1700,1,0x98)
|
||||
ROM_FILL(0x1701,1,0x2)
|
||||
ROM_FILL(0x1833,1,0xd6) //
|
||||
ROM_FILL(0x1834,1,0x2) //
|
||||
ROM_FILL(0x184a,1,0xd6) //
|
||||
ROM_FILL(0x184b,1,0x2) //
|
||||
ROM_FILL(0x1a2e,1,0xd6) //
|
||||
ROM_FILL(0x1a2f,1,0x2) //
|
||||
ROM_FILL(0x19c2,1,0x98)
|
||||
ROM_FILL(0x19c3,1,0x2)
|
||||
ROM_FILL(0x1ee0,1,0x98)
|
||||
ROM_FILL(0x1ee1,1,0x2)
|
||||
ROM_FILL(0x1f1d,1,0x98)
|
||||
ROM_FILL(0x1f1e,1,0x2)
|
||||
ROM_FILL(0x1f40,1,0x98)
|
||||
ROM_FILL(0x1f41,1,0x2)
|
||||
ROM_FILL(0x2253,1,0x98)
|
||||
ROM_FILL(0x2254,1,0x2)
|
||||
ROM_FILL(0x2437,1,0x98)
|
||||
ROM_FILL(0x2438,1,0x2)
|
||||
ROM_FILL(0x283a,1,0x98)
|
||||
ROM_FILL(0x283b,1,0x2)
|
||||
ROM_FILL(0x2868,1,0x98)
|
||||
ROM_FILL(0x2869,1,0x2)
|
||||
ROM_FILL(0x288f,1,0x98)
|
||||
ROM_FILL(0x2890,1,0x2)
|
||||
ROM_FILL(0x2942,1,0x98)
|
||||
ROM_FILL(0x2943,1,0x2)
|
||||
ROM_FILL(0x295c,1,0x98)
|
||||
ROM_FILL(0x295d,1,0x2)
|
||||
ROM_FILL(0x2a5e,1,0x98)
|
||||
ROM_FILL(0x2a5f,1,0x2)
|
||||
ROM_FILL(0x315c,1,0xc9) //
|
||||
ROM_FILL(0x315d,1,0x2) //
|
||||
ROM_FILL(0x3160,1,0xce) //
|
||||
ROM_FILL(0x3161,1,0x2) //
|
||||
ROM_FILL(0x3164,1,0xcf) //
|
||||
ROM_FILL(0x3165,1,0x2) //
|
||||
ROM_END
|
||||
|
||||
ROM_START( grid1131 )
|
||||
ROM_REGION16_LE(0x10000, "user1", 0)
|
||||
|
||||
ROM_SYSTEM_BIOS(0, "ccos", "ccos bios")
|
||||
ROMX_LOAD("1131EVEN.BIN", 0x0000, 0x2000, NO_DUMP, ROM_SKIP(1)|ROM_BIOS(1))
|
||||
ROMX_LOAD("1131ODD.BIN", 0x0001, 0x2000, NO_DUMP, ROM_SKIP(1)|ROM_BIOS(1))
|
||||
ROM_END
|
||||
|
||||
ROM_START( grid1139 )
|
||||
ROM_REGION16_LE(0x10000, "user1", 0)
|
||||
|
||||
ROM_SYSTEM_BIOS(0, "normal", "normal bios")
|
||||
ROMX_LOAD("1139EVEN.BIN", 0x0000, 0x2000, CRC(67071849) SHA1(782239c155fa5821f8dbd2607cee9152d175e90e),ROM_SKIP(1)|ROM_BIOS(1))
|
||||
ROMX_LOAD("1139ODD.BIN", 0x0001, 0x2000, CRC(13ed4bf0) SHA1(f7087f86dbbc911bee985125bccd2417e0374e8e),ROM_SKIP(1)|ROM_BIOS(1))
|
||||
ROM_END
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
|
||||
Game driver(s)
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
// YEAR NAME PARENT COMPAT MACHINE INPUT STATE INIT COMPANY FULLNAME FLAGS
|
||||
COMP( 1982, grid1101, 0, 0, grid1101, gridcomp, gridcomp_state, 0, "GRiD Computers", "Compass 1101", MACHINE_IS_SKELETON )
|
||||
COMP( 1982, grid1109, grid1101, 0, grid1109, gridcomp, gridcomp_state, 0, "GRiD Computers", "Compass 1109", MACHINE_IS_SKELETON )
|
||||
COMP( 1984, grid1121, 0, 0, grid1121, gridcomp, gridcomp_state, 0, "GRiD Computers", "Compass II 1121", MACHINE_IS_SKELETON )
|
||||
COMP( 1984, grid1129, grid1121, 0, grid1129, gridcomp, gridcomp_state, 0, "GRiD Computers", "Compass II 1129", MACHINE_IS_SKELETON )
|
||||
COMP( 1984, grid1131, grid1121, 0, grid1131, gridcomp, gridcomp_state, 0, "GRiD Computers", "Compass II 1131", MACHINE_IS_SKELETON )
|
||||
COMP( 1984, grid1139, grid1121, 0, grid1139, gridcomp, gridcomp_state, 0, "GRiD Computers", "Compass II 1139", MACHINE_IS_SKELETON )
|
||||
|
321
src/mame/machine/gridkeyb.cpp
Normal file
321
src/mame/machine/gridkeyb.cpp
Normal file
@ -0,0 +1,321 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Vas Crabb, Sergey Svishchev
|
||||
/***************************************************************************
|
||||
|
||||
GRiD Compass keyboard HLE, derived from generic_keyboard
|
||||
|
||||
Keycodes from "6 - Interceptor, CCProm, Utils, OS - Sysgen/UTILS/DVLEXEC.PLM"
|
||||
|
||||
Multiple shift key combos not simulated yet.
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
|
||||
#include "machine/gridkeyb.h"
|
||||
#include "machine/keyboard.ipp"
|
||||
|
||||
|
||||
|
||||
namespace {
|
||||
u16 const TRANSLATION_TABLE[][4][16] = {
|
||||
{ // plain
|
||||
{ '`', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', 0x08U, 0x7fU, 0x1bU },
|
||||
{ 0x09U, 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\\', 0xffU, 0xffU },
|
||||
{ 0xffU, 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', 0x0dU, 0xc5U, 0xc4U, 0x0aU },
|
||||
{ 0xffU, '\\', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', 0xffU, 0xc6U, 0xc7U, ' ' }
|
||||
},
|
||||
{ // SHIFT
|
||||
{ '~', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+', 0x08U, 0x7fU, 0x1bU },
|
||||
{ 0x09U, 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', '|', 0xffU, 0xffU },
|
||||
{ 0xffU, 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', '"', 0x0dU, 0xffU, 0xffU, 0x0aU },
|
||||
{ 0xffU, '_', 'Z', 'X', 'C', 'V', 'B', 'N', 'M', '<', '>', '?', 0xffU, 0xffU, 0xffU, ' ' }
|
||||
},
|
||||
{ // CODE -- partial
|
||||
{ 0xffU, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', 0xffU, 0xffU, 0x88U, 0xffU, 0x9bU },
|
||||
{ 0x89U, 0xf1U, 0xf7U, 0xe5U, 0xf2U, 0xf4U, 0xf9U, 0xf5U, 0xe9U, 0xefU, 0xf0U, 0x9bU, 0xffU, 0xffU, 0xffU, 0xffU },
|
||||
{ 0xffU, 0xe1U, 0xf3U, 0xe4U, 0xe6U, 0xe7U, 0xe8U, 0xeaU, 0xebU, 0xecU, ';', '\'', 0x8dU, 0xffU, 0xffU, 0xffU },
|
||||
{ 0xffU, 0x1cU, 0xfaU, 0xf8U, 0xe3U, 0xf6U, 0xe2U, 0xeeU, 0xedU, ',', '.', 0xbfU, 0xffU, 0xd4U, 0xd5U, 0xffU }
|
||||
},
|
||||
{ // CTRL
|
||||
{ 0x00U, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', 0x1fU, 0x1eU, 0x88U, 0x7fU, 0x1bU },
|
||||
{ 0x89U, 0x11U, 0x17U, 0x05U, 0x12U, 0x14U, 0x19U, 0x15U, 0x09U, 0x0fU, 0x10U, 0x9bU, 0x1dU, 0x1cU, 0xffU, 0xffU },
|
||||
{ 0xffU, 0x01U, 0x13U, 0x04U, 0x06U, 0x07U, 0x08U, 0x0aU, 0x0bU, 0x0cU, ';', '\'', 0x8dU, 0xffU, 0xffU, 0x0aU },
|
||||
{ 0xffU, 0x1cU, 0x1aU, 0x18U, 0x03U, 0x16U, 0x02U, 0x0eU, 0x0dU, ',', '.', 0xbfU, 0xffU, 0xffU, 0xffU, 0x00U }
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
bool const CAPS_TABLE[4][16] = {
|
||||
{ false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false },
|
||||
{ false, true, true, true, true, true, true, true, true, true, true, false, false, false, false, false },
|
||||
{ false, true, true, true, true, true, true, true, true, true, false, false, false, false, false, false },
|
||||
{ false, false, true, true, true, true, true, true, true, false, false, false, false, false, false, false }
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
REUSABLE I/O PORTS
|
||||
***************************************************************************/
|
||||
|
||||
INPUT_PORTS_START( grid_keyboard )
|
||||
PORT_START("GRIDKBD_CFG")
|
||||
PORT_CONFNAME( 0x0006U, 0x0004U, "Typematic Delay" )
|
||||
PORT_CONFSETTING( 0x0000U, "0.25s" )
|
||||
PORT_CONFSETTING( 0x0002U, "0.5s" )
|
||||
PORT_CONFSETTING( 0x0004U, "0.75s" )
|
||||
PORT_CONFSETTING( 0x0006U, "1.0s" )
|
||||
PORT_CONFNAME( 0x00f8U, 0x0098U, "Typematic Rate" )
|
||||
PORT_CONFSETTING( 0x0000U, "2.0cps" )
|
||||
PORT_CONFSETTING( 0x0008U, "2.1cps" )
|
||||
PORT_CONFSETTING( 0x0010U, "2.5cps" )
|
||||
PORT_CONFSETTING( 0x0018U, "2.7cps" )
|
||||
PORT_CONFSETTING( 0x0020U, "2.0cps" )
|
||||
PORT_CONFSETTING( 0x0028U, "2.1cps" )
|
||||
PORT_CONFSETTING( 0x0030U, "2.5cps" )
|
||||
PORT_CONFSETTING( 0x0038U, "2.7cps" )
|
||||
PORT_CONFSETTING( 0x0040U, "3.3cps" )
|
||||
PORT_CONFSETTING( 0x0048U, "3.8cps" )
|
||||
PORT_CONFSETTING( 0x0050U, "4.0cps" )
|
||||
PORT_CONFSETTING( 0x0058U, "4.3cps" )
|
||||
PORT_CONFSETTING( 0x0060U, "4.6cps" )
|
||||
PORT_CONFSETTING( 0x0068U, "5.0cps" )
|
||||
PORT_CONFSETTING( 0x0070U, "5.5cps" )
|
||||
PORT_CONFSETTING( 0x0078U, "6.0cps" )
|
||||
PORT_CONFSETTING( 0x0080U, "8.0cps" )
|
||||
PORT_CONFSETTING( 0x0088U, "8.6cps" )
|
||||
PORT_CONFSETTING( 0x0090U, "9.2cps" )
|
||||
PORT_CONFSETTING( 0x0098U, "10.0cps" )
|
||||
PORT_CONFSETTING( 0x00a0U, "10.9cps" )
|
||||
PORT_CONFSETTING( 0x00a8U, "12.0cps" )
|
||||
PORT_CONFSETTING( 0x00b0U, "13.3cps" )
|
||||
PORT_CONFSETTING( 0x00b8U, "15.0cps" )
|
||||
PORT_CONFSETTING( 0x00c0U, "16.0cps" )
|
||||
PORT_CONFSETTING( 0x00c8U, "17.1cps" )
|
||||
PORT_CONFSETTING( 0x00d0U, "18.5cps" )
|
||||
PORT_CONFSETTING( 0x00d8U, "20.0cps" )
|
||||
PORT_CONFSETTING( 0x00e0U, "21.8cps" )
|
||||
PORT_CONFSETTING( 0x00e8U, "24.0cps" )
|
||||
PORT_CONFSETTING( 0x00f0U, "26.7cps" )
|
||||
PORT_CONFSETTING( 0x00f8U, "30.0cps" )
|
||||
|
||||
PORT_START("GRIDKBD_MOD")
|
||||
PORT_BIT( 0x01U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Ctrl") PORT_CODE(KEYCODE_LCONTROL) PORT_CODE(KEYCODE_RCONTROL) PORT_CHAR(UCHAR_MAMEKEY(LCONTROL))
|
||||
PORT_BIT( 0x02U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Shift") PORT_CODE(KEYCODE_LSHIFT) PORT_CODE(KEYCODE_RSHIFT) PORT_CHAR(UCHAR_SHIFT_1)
|
||||
PORT_BIT( 0x04U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Caps Lock") PORT_CODE(KEYCODE_CAPSLOCK) PORT_TOGGLE PORT_CHAR(UCHAR_MAMEKEY(CAPSLOCK))
|
||||
PORT_BIT( 0x08U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Code") PORT_CODE(KEYCODE_LALT) PORT_CODE(KEYCODE_RALT) PORT_CHAR(UCHAR_MAMEKEY(LALT))
|
||||
|
||||
PORT_START("GRIDKBD_ROW0")
|
||||
PORT_BIT( 0x0001U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_TILDE) PORT_CHAR('`') PORT_CHAR('~')
|
||||
PORT_BIT( 0x0002U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!')
|
||||
PORT_BIT( 0x0004U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('@')
|
||||
PORT_BIT( 0x0008U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('#')
|
||||
PORT_BIT( 0x0010U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$')
|
||||
PORT_BIT( 0x0020U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%')
|
||||
PORT_BIT( 0x0040U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('^')
|
||||
PORT_BIT( 0x0080U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('&')
|
||||
PORT_BIT( 0x0100U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('*')
|
||||
PORT_BIT( 0x0200U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR('(')
|
||||
PORT_BIT( 0x0400U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR('(')
|
||||
PORT_BIT( 0x0800U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-') PORT_CHAR('_')
|
||||
PORT_BIT( 0x1000U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('=') PORT_CHAR('+')
|
||||
PORT_BIT( 0x2000U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_BACKSPACE) PORT_NAME("Backspace") PORT_CHAR(0x08U)
|
||||
PORT_BIT( 0x4000U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_DEL) PORT_NAME("Del") PORT_CHAR(UCHAR_MAMEKEY(DEL))
|
||||
PORT_BIT( 0x8000U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_ESC) PORT_NAME("Escape") PORT_CHAR(UCHAR_MAMEKEY(ESC))
|
||||
|
||||
PORT_START("GRIDKBD_ROW1")
|
||||
PORT_BIT( 0x0001U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_TAB) PORT_CHAR('\t')
|
||||
PORT_BIT( 0x0002U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q')
|
||||
PORT_BIT( 0x0004U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_W) PORT_CHAR('w') PORT_CHAR('W')
|
||||
PORT_BIT( 0x0008U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_E) PORT_CHAR('e') PORT_CHAR('E')
|
||||
PORT_BIT( 0x0010U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_R) PORT_CHAR('r') PORT_CHAR('R')
|
||||
PORT_BIT( 0x0020U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_T) PORT_CHAR('t') PORT_CHAR('T')
|
||||
PORT_BIT( 0x0040U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_Y) PORT_CHAR('y') PORT_CHAR('Y')
|
||||
PORT_BIT( 0x0080U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_U) PORT_CHAR('u') PORT_CHAR('U')
|
||||
PORT_BIT( 0x0100U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_I) PORT_CHAR('i') PORT_CHAR('I')
|
||||
PORT_BIT( 0x0200U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O')
|
||||
PORT_BIT( 0x0400U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_P) PORT_CHAR('p') PORT_CHAR('P')
|
||||
PORT_BIT( 0x0800U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR('[') PORT_CHAR('{')
|
||||
PORT_BIT( 0x1000U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR(']') PORT_CHAR('}')
|
||||
PORT_BIT( 0x2000U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR('\\') PORT_CHAR('|')
|
||||
PORT_BIT( 0x4000U, IP_ACTIVE_HIGH, IPT_UNUSED )
|
||||
PORT_BIT( 0x8000U, IP_ACTIVE_HIGH, IPT_UNUSED )
|
||||
|
||||
PORT_START("GRIDKBD_ROW2")
|
||||
PORT_BIT( 0x0001U, IP_ACTIVE_HIGH, IPT_UNUSED )
|
||||
PORT_BIT( 0x0002U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_A) PORT_CHAR('a') PORT_CHAR('A')
|
||||
PORT_BIT( 0x0004U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_S) PORT_CHAR('s') PORT_CHAR('S')
|
||||
PORT_BIT( 0x0008U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_D) PORT_CHAR('d') PORT_CHAR('D')
|
||||
PORT_BIT( 0x0010U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F) PORT_CHAR('f') PORT_CHAR('F')
|
||||
PORT_BIT( 0x0020U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_G) PORT_CHAR('g') PORT_CHAR('G')
|
||||
PORT_BIT( 0x0040U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_H) PORT_CHAR('h') PORT_CHAR('H')
|
||||
PORT_BIT( 0x0080U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_J) PORT_CHAR('j') PORT_CHAR('J')
|
||||
PORT_BIT( 0x0100U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_K) PORT_CHAR('k') PORT_CHAR('K')
|
||||
PORT_BIT( 0x0200U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_L) PORT_CHAR('l') PORT_CHAR('L')
|
||||
PORT_BIT( 0x0400U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_COLON) PORT_CHAR(';') PORT_CHAR(':')
|
||||
PORT_BIT( 0x0800U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR('\'') PORT_CHAR('"')
|
||||
PORT_BIT( 0x1000U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_ENTER) PORT_NAME("Return") PORT_CHAR(0x0dU)
|
||||
PORT_BIT( 0x2000U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_UP) PORT_NAME("UpArrow")
|
||||
PORT_BIT( 0x4000U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_DOWN) PORT_NAME("DownArrow")
|
||||
PORT_BIT( 0x8000U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_INSERT) PORT_NAME("Linefeed") PORT_CHAR(UCHAR_MAMEKEY(INSERT))
|
||||
|
||||
PORT_START("GRIDKBD_ROW3")
|
||||
PORT_BIT( 0x0001U, IP_ACTIVE_HIGH, IPT_UNUSED )
|
||||
PORT_BIT( 0x0002U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_BACKSLASH2) PORT_CHAR('\\') PORT_CHAR('_')
|
||||
PORT_BIT( 0x0004U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_Z) PORT_CHAR('z') PORT_CHAR('Z')
|
||||
PORT_BIT( 0x0008U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X')
|
||||
PORT_BIT( 0x0010U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_C) PORT_CHAR('c') PORT_CHAR('C')
|
||||
PORT_BIT( 0x0020U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V')
|
||||
PORT_BIT( 0x0040U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_B) PORT_CHAR('b') PORT_CHAR('B')
|
||||
PORT_BIT( 0x0080U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_N) PORT_CHAR('n') PORT_CHAR('N')
|
||||
PORT_BIT( 0x0100U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_M) PORT_CHAR('m') PORT_CHAR('M')
|
||||
PORT_BIT( 0x0200U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR('<')
|
||||
PORT_BIT( 0x0400U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR('>')
|
||||
PORT_BIT( 0x0800U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_SLASH) PORT_CHAR('/') PORT_CHAR('?')
|
||||
PORT_BIT( 0x1000U, IP_ACTIVE_HIGH, IPT_UNUSED )
|
||||
PORT_BIT( 0x2000U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_LEFT) PORT_NAME("LeftArrow")
|
||||
PORT_BIT( 0x4000U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_RIGHT) PORT_NAME("RightArrow")
|
||||
PORT_BIT( 0x8000U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ')
|
||||
INPUT_PORTS_END
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
DEVICE TYPE GLOBALS
|
||||
***************************************************************************/
|
||||
|
||||
DEFINE_DEVICE_TYPE(GRID_KEYBOARD, grid_keyboard_device, "grid_keyboard", "GRiD Compass Keyboard")
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
IMPLEMENTATION
|
||||
***************************************************************************/
|
||||
|
||||
grid_keyboard_device::grid_keyboard_device(
|
||||
machine_config const &mconfig,
|
||||
device_type type,
|
||||
char const *tag,
|
||||
device_t *owner,
|
||||
u32 clock)
|
||||
: device_t(mconfig, type, tag, owner, clock)
|
||||
, device_matrix_keyboard_interface(mconfig, *this, "GRIDKBD_ROW0", "GRIDKBD_ROW1", "GRIDKBD_ROW2", "GRIDKBD_ROW3")
|
||||
, m_config(*this, "GRIDKBD_CFG")
|
||||
, m_modifiers(*this, "GRIDKBD_MOD")
|
||||
, m_last_modifiers(0U)
|
||||
, m_keyboard_cb()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
grid_keyboard_device::grid_keyboard_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
|
||||
: grid_keyboard_device(mconfig, GRID_KEYBOARD, tag, owner, clock)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
ioport_constructor grid_keyboard_device::device_input_ports() const
|
||||
{
|
||||
return INPUT_PORTS_NAME(grid_keyboard);
|
||||
}
|
||||
|
||||
|
||||
void grid_keyboard_device::device_start()
|
||||
{
|
||||
m_keyboard_cb.bind_relative_to(*owner());
|
||||
|
||||
save_item(NAME(m_last_modifiers));
|
||||
}
|
||||
|
||||
|
||||
void grid_keyboard_device::device_reset()
|
||||
{
|
||||
reset_key_state();
|
||||
m_last_modifiers = 0;
|
||||
|
||||
start_processing(attotime::from_hz(2'400));
|
||||
typematic_stop();
|
||||
}
|
||||
|
||||
|
||||
void grid_keyboard_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
|
||||
{
|
||||
device_matrix_keyboard_interface::device_timer(timer, id, param, ptr);
|
||||
}
|
||||
|
||||
|
||||
void grid_keyboard_device::key_make(u8 row, u8 column)
|
||||
{
|
||||
send_translated((row << 4) | column);
|
||||
typematic_start(row, column, typematic_delay(), typematic_period());
|
||||
}
|
||||
|
||||
|
||||
void grid_keyboard_device::key_repeat(u8 row, u8 column)
|
||||
{
|
||||
send_translated((row << 4) | column);
|
||||
}
|
||||
|
||||
|
||||
void grid_keyboard_device::send_key(u16 code)
|
||||
{
|
||||
m_keyboard_cb(code);
|
||||
}
|
||||
|
||||
|
||||
bool grid_keyboard_device::translate(u8 code, u16 &translated) const
|
||||
{
|
||||
unsigned const row((code >> 4) & 0x03U);
|
||||
unsigned const col((code >> 0) & 0x0fU);
|
||||
|
||||
u16 const modifiers(m_modifiers->read());
|
||||
bool const shift(bool(modifiers & 0x02U) != (bool(modifiers & 0x04U) && CAPS_TABLE[row][col]));
|
||||
bool const ctrl(modifiers & 0x01U);
|
||||
bool const meta(modifiers & 0x08U);
|
||||
|
||||
unsigned const map(ctrl ? 3U : meta ? 2U : shift ? 1U : 0U);
|
||||
u16 const result(TRANSLATION_TABLE[map][row][col]);
|
||||
if (result == u8(~0U))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
translated = result;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void grid_keyboard_device::will_scan_row(u8 row)
|
||||
{
|
||||
u16 const modifiers(m_modifiers->read());
|
||||
if (modifiers != m_last_modifiers)
|
||||
typematic_restart(typematic_delay(), typematic_period());
|
||||
|
||||
m_last_modifiers = modifiers;
|
||||
}
|
||||
|
||||
|
||||
void grid_keyboard_device::send_translated(u8 code)
|
||||
{
|
||||
u16 translated;
|
||||
if (translate(code, translated))
|
||||
send_key(translated);
|
||||
}
|
||||
|
||||
|
||||
attotime grid_keyboard_device::typematic_delay() const
|
||||
{
|
||||
return attotime::from_msec(250 * (1 + ((m_config->read() >> 1) & 0x03U)));
|
||||
}
|
||||
|
||||
|
||||
attotime grid_keyboard_device::typematic_period() const
|
||||
{
|
||||
unsigned const rate(~(m_config->read() >> 3) & 0x1fU);
|
||||
return attotime::from_ticks((8U + (rate & 0x07U)) * (1 << ((rate >> 3) & 0x03)), 240U);
|
||||
}
|
89
src/mame/machine/gridkeyb.h
Normal file
89
src/mame/machine/gridkeyb.h
Normal file
@ -0,0 +1,89 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Vas Crabb, Sergey Svishchev
|
||||
#ifndef MAME_MACHINE_GRIDKEYB_H
|
||||
#define MAME_MACHINE_GRIDKEYB_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "machine/keyboard.h"
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
DEVICE CONFIGURATION MACROS
|
||||
***************************************************************************/
|
||||
|
||||
#define GRIDKEYBCB_PUT(cls, fnc) grid_keyboard_device::output_delegate((&cls::fnc), (#cls "::" #fnc), DEVICE_SELF, ((cls *)nullptr))
|
||||
#define GRIDKEYBCB_DEVPUT(tag, cls, fnc) grid_keyboard_device::output_delegate((&cls::fnc), (#cls "::" #fnc), (tag), ((cls *)nullptr))
|
||||
|
||||
#define MCFG_GRID_KEYBOARD_CB(cb) \
|
||||
grid_keyboard_device::set_keyboard_callback(*device, (GRIDKEYBCB_##cb));
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
DEVICE TYPE GLOBALS
|
||||
***************************************************************************/
|
||||
|
||||
DECLARE_DEVICE_TYPE(GRID_KEYBOARD, grid_keyboard_device)
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
REUSABLE I/O PORTS
|
||||
***************************************************************************/
|
||||
|
||||
INPUT_PORTS_EXTERN( grid_keyboard );
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
TYPE DECLARATIONS
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
class grid_keyboard_device : public device_t, protected device_matrix_keyboard_interface<4U>
|
||||
{
|
||||
public:
|
||||
typedef device_delegate<void (u16 character)> output_delegate;
|
||||
|
||||
grid_keyboard_device(
|
||||
const machine_config &mconfig,
|
||||
const char *tag,
|
||||
device_t *owner,
|
||||
u32 clock);
|
||||
|
||||
template <class Object> static void set_keyboard_callback(device_t &device, Object &&cb) { downcast<grid_keyboard_device &>(device).m_keyboard_cb = std::forward<Object>(cb); }
|
||||
|
||||
virtual ioport_constructor device_input_ports() const override;
|
||||
|
||||
protected:
|
||||
grid_keyboard_device(
|
||||
const machine_config &mconfig,
|
||||
device_type type,
|
||||
char const *tag,
|
||||
device_t *owner,
|
||||
u32 clock);
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
|
||||
virtual void key_make(u8 row, u8 column) override;
|
||||
virtual void key_repeat(u8 row, u8 column) override;
|
||||
virtual void send_key(u16 code);
|
||||
virtual bool translate(u8 code, u16 &translated) const;
|
||||
|
||||
required_ioport m_config;
|
||||
required_ioport m_modifiers;
|
||||
|
||||
private:
|
||||
virtual void will_scan_row(u8 row) override;
|
||||
|
||||
void typematic();
|
||||
void send_translated(u8 code);
|
||||
attotime typematic_delay() const;
|
||||
attotime typematic_period() const;
|
||||
|
||||
u16 m_last_modifiers;
|
||||
output_delegate m_keyboard_cb;
|
||||
};
|
||||
|
||||
#endif // MAME_MACHINE_GRIDKEYB_H
|
@ -14024,6 +14024,14 @@ grchamp // GM (c) 1981 Taito Corporation
|
||||
@source:grfd2301.cpp
|
||||
grfd2301 //
|
||||
|
||||
@source:gridcomp.cpp
|
||||
grid1101 //
|
||||
grid1109 //
|
||||
grid1121 //
|
||||
grid1129 //
|
||||
grid1131 //
|
||||
grid1139 //
|
||||
|
||||
@source:gridlee.cpp
|
||||
gridlee // [1983 Videa] prototype - no copyright notice
|
||||
|
||||
|
@ -226,6 +226,7 @@ goupil.cpp
|
||||
gp2x.cpp
|
||||
gp32.cpp
|
||||
grfd2301.cpp
|
||||
gridcomp.cpp
|
||||
h19.cpp
|
||||
h8.cpp
|
||||
h89.cpp
|
||||
|
Loading…
Reference in New Issue
Block a user