Revert "Alfaskop improvements"

This commit is contained in:
Vas Crabb 2020-01-31 20:05:02 +11:00 committed by GitHub
parent 7d5c59f6e5
commit bddfe1030c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 164 additions and 1823 deletions

View File

@ -1895,18 +1895,6 @@ if (MACHINES["MC6843"]~=null) then
}
end
---------------------------------------------------
--
--@src/devices/machine/mc6844.h,MACHINES["MC6844"] = true
---------------------------------------------------
if (MACHINES["MC6844"]~=null) then
files {
MAME_DIR .. "src/devices/machine/mc6844.cpp",
MAME_DIR .. "src/devices/machine/mc6844.h",
}
end
---------------------------------------------------
--
--@src/devices/machine/mc6846.h,MACHINES["MC6846"] = true

View File

@ -545,7 +545,6 @@ MACHINES["MC14411"] = true
MACHINES["MC146818"] = true
MACHINES["MC2661"] = true
MACHINES["MC6843"] = true
MACHINES["MC6844"] = true
MACHINES["MC6846"] = true
MACHINES["MC6852"] = true
MACHINES["MC6854"] = true
@ -2241,9 +2240,6 @@ files {
MAME_DIR .. "src/mame/drivers/eispc.cpp",
MAME_DIR .. "src/mame/machine/eispc_kb.cpp",
MAME_DIR .. "src/mame/machine/eispc_kb.h",
MAME_DIR .. "src/mame/drivers/alfaskop41xx.cpp",
MAME_DIR .. "src/mame/machine/alfaskop_s41_kb.cpp",
MAME_DIR .. "src/mame/machine/alfaskop_s41_kb.h",
}
createMESSProjects(_target, _subtarget, "exidy")

View File

@ -17,8 +17,7 @@
#define LOG_SETUP 0x02
#define LOG_CA1 0x08
//#define VERBOSE (LOG_SETUP | LOG_GENERAL | LOG_CA1)
//#define LOG_OUTPUT_STREAM std::cout
//#define VERBOSE (LOG_SETUP | LOG_GENERAL)
#include "logmacro.h"
#define LOGSETUP(...) LOGMASKED(LOG_SETUP, __VA_ARGS__)
@ -597,7 +596,7 @@ void pia6821_device::send_to_out_a_func(const char* message)
// input pins are pulled high
const uint8_t data = get_out_a_value();
LOG("PIA %s = %02X DDRA=%02x\n", message, data, m_ddr_a);
LOG("PIA %s = %02X\n", message, data);
if (!m_out_a_handler.isnull())
{
@ -622,7 +621,7 @@ void pia6821_device::send_to_out_b_func(const char* message)
// input pins are high-impedance - we just send them as zeros for backwards compatibility
const uint8_t data = get_out_b_value();
LOG("PIA %s = %02X DDRB=%02x\n", message, data, m_ddr_b);
LOG("PIA %s = %02X\n", message, data);
if (!m_out_b_handler.isnull())
{
@ -647,7 +646,6 @@ void pia6821_device::port_a_w(uint8_t data)
// buffer the output value
m_out_a = data;
LOGSETUP("PIA ");
send_to_out_a_func("port A write");
}
@ -722,9 +720,6 @@ void pia6821_device::control_a_w(uint8_t data)
data &= 0x3f;
LOGSETUP("PIA control A write = %02X\n", data);
LOGSETUP(" - CA1 interrupts %s\n", (data & 0x01) ? "enabled" : "disabled");
LOGSETUP(" - CA1 interrupts active on %s transition\n", (data & 0x02) ? "low-to-high" : "high-to-low");
LOGSETUP(" - Port A %s register selected\n", (data & 0x04) ? "Data" : "DDR");
// update the control register
m_ctl_a = data;
@ -734,17 +729,10 @@ void pia6821_device::control_a_w(uint8_t data)
{
bool temp;
if (c2_set_mode(m_ctl_a))
{
LOGSETUP(" - CA2 set/reset mode: ");
temp = c2_set(m_ctl_a); // set/reset mode - bit value determines the new output
}
else
{
LOGSETUP(" - CA2 strobe mode: ");
temp = true; // strobe mode - output is always high unless strobed
}
LOGSETUP("%d\n", temp);
set_out_ca2(temp);
}
@ -763,26 +751,16 @@ void pia6821_device::control_b_w(uint8_t data)
data &= 0x3f;
LOGSETUP("PIA control B write = %02X\n", data);
LOGSETUP(" - CB1 interrupts %s\n", (data & 0x01) ? "enabled" : "disabled");
LOGSETUP(" - CB1 interrupts active on %s transition\n", (data & 0x02) ? "low-to-high" : "high-to-low");
LOGSETUP(" - Port B %s register selected\n", (data & 0x04) ? "Data" : "DDR");
// update the control register
m_ctl_b = data;
bool temp;
if (c2_set_mode(m_ctl_b))
{
LOGSETUP(" - CB2 set/reset mode: ");
temp = c2_set(m_ctl_b); // set/reset mode - bit value determines the new output
}
else
{
LOGSETUP(" - CB2 strobe mode: ");
temp = true; // strobe mode - output is always high unless strobed
}
LOGSETUP("%d\n", temp);
set_out_cb2(temp);
// update externals

View File

@ -16,15 +16,10 @@
MACROS
***************************************************************************/
#define LOG_SETUP (1U << 1)
//#define VERBOSE (LOG_GENERAL | LOG_SETUP)
//#define VERBOSE 1
//#define LOG_OUTPUT_STREAM std::cout
#include "logmacro.h"
#define LOGSETUP(...) LOGMASKED(LOG_SETUP, __VA_ARGS__)
/***************************************************************************
LOCAL VARIABLES
***************************************************************************/
@ -182,14 +177,12 @@ void acia6850_device::control_w(uint8_t data)
// CR0 & CR1
int counter_divide_select_bits = (data >> 0) & 3;
m_divide = counter_divide_select[counter_divide_select_bits];
LOGSETUP(" - Divide: x%d\n", counter_divide_select[counter_divide_select_bits]);
// CR2, CR3 & CR4
int word_select_bits = (data >> 2) & 7;
m_bits = word_select[word_select_bits][0];
m_parity = word_select[word_select_bits][1];
m_stopbits = word_select[word_select_bits][2];
LOGSETUP(" - %d%c%d\n", m_bits, m_parity == PARITY_NONE ? 'N' : (m_parity == PARITY_ODD ? 'O' : 'E'), m_stopbits);
// CR5 & CR6
int transmitter_control_bits = (data >> 5) & 3;
@ -199,7 +192,6 @@ void acia6850_device::control_w(uint8_t data)
// CR7
m_rx_irq_enable = (data >> 7) & 1;
LOGSETUP(" - RTS:%d BRK:%d TxIE:%d RxIE:%d\n", rts, m_brk, m_tx_irq_enable, m_rx_irq_enable);
if (m_divide == 0)
{

View File

@ -1,561 +0,0 @@
// license:BSD-3-Clause
// copyright-holders: Joakim Larsson Edström
/**********************************************************************
Motorola 6844 emulation. This code is not yet ready for general use, see TODO list below
"MC6844 — Direct Memory Access Controller
This DMAC works with an M6800 MPU Clock Pulse Generator and an I/O Peripheral Controller,
such as the units described here, to facilitate direct access to the computer memory by
the peripheral, thus by passing MPU interactive time delay.
General Description
The MC6844 is operable in three modes: HALT Burst, Cycle Steal and TSC Steal.
In the Burst Mode, the MPU is halted by the first transfer request (TxRQ) input and
is restarted when the Byte Count Register (BCR) is zero. Each data transfer is synchronized
by a pulse input of TxRQ. In the Cycle Steal Mode, the MPU is halted by each TxRQ and
is restarted after each one byte of data transferred. In the TSC Steal Mode, DMAC uses the
three-state control function of the MPU to control the system bus. One byte of data is
transferred during each DMA cycle.
The DMAC has four channels. A Priority Control Register determines which of the channels
is enabled. While data is being transferred on one channel, the other channels are inhibited.
When one channel completes transferring, the next will become valid for DMA transfer. The PCR
also utilizes a Rotate Control bit. Priority of DMA transfer is normally fixed in sequential
order. The highest priority is in #0 Channel and the lowest is in #3. When this bit is in high
level, channel priority is rotated such that the just-serviced channel has the lowest priority
in the next DMA transfer."
Source: https://en.wikipedia.org/wiki/File:Motorola_Microcomputer_Components_1978_pg13.jpg
CREDITS & Prior Work:
The base code was ripped out of swtpc09.cpp and deviceified but similar code is also to be found
in exidy440.cpp so copyrigt is probably shared among the authors there: Robert Justice, 68bit and
Aaron Giles.
TODO:
- Memory to Device transfers
**********************************************************************/
#include "emu.h"
#include "mc6844.h"
//**************************************************************************
// GLOBAL VARIABLES
//**************************************************************************
#define LOG_SETUP (1U << 1)
#define LOG_INT (1U << 2)
#define LOG_STATE (1U << 3)
#define LOG_TFR (1U << 4)
//#define VERBOSE (LOG_GENERAL|LOG_SETUP | LOG_INT | LOG_STATE |LOG_TFR)
//#define LOG_OUTPUT_STREAM std::cout
#include "logmacro.h"
#define LOGSETUP(...) LOGMASKED(LOG_SETUP, __VA_ARGS__)
#define LOGINT(...) LOGMASKED(LOG_INT, __VA_ARGS__)
#define LOGSTATE(...) LOGMASKED(LOG_STATE, __VA_ARGS__)
#define LOGTFR(...) LOGMASKED(LOG_TFR, __VA_ARGS__)
#ifdef _MSC_VER
#define FUNCNAME __func__
#else
#define FUNCNAME __PRETTY_FUNCTION__
#endif
// device type definition
DEFINE_DEVICE_TYPE(MC6844, mc6844_device, "mc6844", "MC6844 DMA")
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
//-------------------------------------------------
// mc6844_device - constructor
//-------------------------------------------------
mc6844_device::mc6844_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, MC6844, tag, owner, clock)
, device_execute_interface(mconfig, *this)
, m_out_int_cb(*this)
, m_out_txak_cb(*this)
, m_out_drq1_cb(*this)
, m_out_drq2_cb(*this)
, m_in_memr_cb(*this)
, m_out_memw_cb(*this)
, m_in_ior_cb{ { *this },{ *this },{ *this },{ *this } }
, m_out_iow_cb{ { *this },{ *this },{ *this },{ *this } }
, m_state(STATE_S0)
, m_icount(0)
{
}
//-------------------------------------------------
// device_resolve_objects - device-specific setup
//-------------------------------------------------
void mc6844_device::device_resolve_objects()
{
m_out_int_cb.resolve_safe();
m_out_txak_cb.resolve_safe();
m_out_drq1_cb.resolve_safe();
m_out_drq2_cb.resolve_safe();
m_in_memr_cb.resolve_safe(0);
m_out_memw_cb.resolve_safe();
for (auto &cb : m_in_ior_cb)
cb.resolve_safe(0);
for (auto &cb : m_out_iow_cb)
cb.resolve_safe();
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void mc6844_device::device_start()
{
// set our instruction counter
set_icountptr(m_icount);
save_item(NAME(m_m6844_priority));
save_item(NAME(m_m6844_interrupt));
save_item(NAME(m_m6844_chain));
save_item(NAME(m_state));
save_item(NAME(m_icount));
save_item(NAME(m_current_channel));
save_item(NAME(m_last_channel));
save_item(NAME(m_dgrnt));
save_item(NAME(m_dreq));
save_item(STRUCT_MEMBER( m_m6844_channel, active));
save_item(STRUCT_MEMBER( m_m6844_channel, address));
save_item(STRUCT_MEMBER( m_m6844_channel, counter));
save_item(STRUCT_MEMBER( m_m6844_channel, control));
save_item(STRUCT_MEMBER( m_m6844_channel, start_address));
save_item(STRUCT_MEMBER( m_m6844_channel, start_counter));
}
//-------------------------------------------------
// device_reset - device-specific reset
//-------------------------------------------------
void mc6844_device::device_reset()
{
// reset the 6844
for (int i = 0; i < 4; i++)
{
m_m6844_channel[i].active = 0;
m_m6844_channel[i].control = 0x00;
}
m_m6844_priority = 0x00;
m_m6844_interrupt = 0x00;
m_m6844_chain = 0x00;
m_state = STATE_SI;
}
//-------------------------------------------------
// dma_request -
//-------------------------------------------------
void mc6844_device::dma_request(int channel, int state)
{
LOG("MC6844 Channel %u DMA Request: %u\n", channel, state);
m_dreq[channel & 3] = state;
LOGSTATE("Trigger(1)\n");
trigger(1);
}
//-------------------------------------------------
// execute_run -
//-------------------------------------------------
void mc6844_device::execute_run()
{
do
{
switch (m_state)
{
case STATE_SI: // IDLE state, will suspend until a DMA request comes through
{ // Hi ------> Lo
int const priorities[][4] = {{ 1, 2, 3, 0 },
{ 2, 3, 0, 1 },
{ 3, 0, 1, 2 },
{ 0, 1, 2, 3 }};
LOGSTATE("DMA state SI\n");
for (int prio = 0; prio < 4; prio++)
{
// Rotating or static channel prioritizations
int current_channel = priorities[((m_m6844_priority & 0x80) ? m_last_channel : 3) & 3][prio];
if (m_m6844_channel[current_channel].active == 1 && m_dreq[current_channel] == ASSERT_LINE)
{
m_current_channel = m_last_channel = current_channel;
m_state = STATE_S0;
break;
}
}
}
if(m_state == STATE_SI)
{
LOGSTATE("Suspend in SI\n");
suspend_until_trigger(1, true);
m_icount = 0;
}
break;
case STATE_S0: // Wait for BCR != 0 and Tx EN == 1
LOGSTATE("DMA state S0\n");
if (m_m6844_channel[m_current_channel].active == 1 &&
m_m6844_channel[m_current_channel].counter != 0)
{
m_state = STATE_S1;
}
else
{
LOGSTATE("Suspend in S0\n");
suspend_until_trigger(1, true);
m_icount = 0;
}
break;
case STATE_S1: // Wait for Tx RQ == 1
LOGSTATE("DMA state S1\n");
if (m_dreq[m_current_channel] == ASSERT_LINE)
{
m_state = STATE_S2;
switch(m_m6844_channel[m_current_channel].control & 0x06)
{
case 0x00: // Mode 2 - single-byte transfer HALT steal mode
case 0x02: // Mode 3 - block transfer mode
m_out_drq2_cb(ASSERT_LINE);
break;
case 0x04: // Mode 1 - single-byte transfer TSC steal mode
m_out_drq1_cb(ASSERT_LINE);
break;
default:
m_out_drq1_cb(CLEAR_LINE);
m_out_drq2_cb(CLEAR_LINE);
break;
}
}
else
{
LOGSTATE("Suspend in S1\n");
suspend_until_trigger(1, true);
m_icount = 0;
}
break;
case STATE_S2: // Wait for DGRNT == 1
LOGSTATE("DMA state S2\n");
if (m_dgrnt == ASSERT_LINE && m_dreq[m_current_channel] == ASSERT_LINE)
{
m_out_txak_cb(m_current_channel);
if (m_m6844_channel[m_current_channel].active == 1) //active dma transfer
{
if (!(m_m6844_channel[m_current_channel].control & 0x01))
{
uint8_t data = m_in_ior_cb[m_current_channel]();
LOGTFR("DMA%d from device to memory location %04x: <- %02x\n", m_current_channel, m_m6844_channel[m_current_channel].address, data );
m_out_memw_cb(m_m6844_channel[m_current_channel].address, data);
}
else // dma write to device from memory
{
uint8_t data = 0;
//uint8_t data = m_in_memr_cb(m_m6844_channel[m_current_channel].address);
LOGTFR("DMA from memory location to device %04x: -> %02x\n", m_m6844_channel[m_current_channel].address, data );
//m_out_iow_cb[m_current_channel](data);
}
if (m_m6844_channel[m_current_channel].control & 0x08)
{
m_m6844_channel[m_current_channel].address--;
}
else
{
m_m6844_channel[m_current_channel].address++;
}
m_m6844_channel[m_current_channel].counter--;
if (m_m6844_channel[m_current_channel].counter == 0)
{
m_out_drq1_cb(CLEAR_LINE);
m_out_drq2_cb(CLEAR_LINE);
m_m6844_channel[m_current_channel].control |= 0x80;
m6844_update_interrupt();
m_state = STATE_SI;
}
else
{
switch(m_m6844_channel[m_current_channel].control & 0x06)
{
case 0x00:
LOGTFR("Mode 2 - single-byte transfer HALT steal mode\n");
m_state = STATE_S1;
m_out_drq2_cb(CLEAR_LINE);
break;
case 0x02:
LOGTFR("Mode 3 - block transfer mode\n");
m_state = STATE_S2; // Just for clarity, we are still in STATE_S2
break;
case 0x04:
LOGTFR("Mode 1 - single-byte transfer TSC steal mode\n");
m_state = STATE_S1;
m_out_drq1_cb(CLEAR_LINE);
break;
default: // Undefined - needs verification on real hardware
logerror("MC6844: undefined transfer mode, clearing DMA request\n");
m_state = STATE_SI;
m_out_drq1_cb(CLEAR_LINE);
m_out_drq2_cb(CLEAR_LINE);
break;
}
}
}
}
else
{
LOGSTATE("Suspend in S2\n");
suspend_until_trigger(1, true);
m_icount = 0;
}
break;
default:
logerror("MC6844: bad state, please report error\n");
break;
}
m_icount--;
} while (m_icount > 0);
}
//**************************************************************************
// READ/WRITE HANDLERS
//**************************************************************************
//-------------------------------------------------
// read handler
//-------------------------------------------------
uint8_t mc6844_device::read(offs_t offset)
{
uint8_t result = 0;
// switch off the offset we were given
switch (offset)
{
// upper byte of address
case 0x00:
case 0x04:
case 0x08:
case 0x0c:
result = m_m6844_channel[offset / 4].address >> 8;
break;
// lower byte of address
case 0x01:
case 0x05:
case 0x09:
case 0x0d:
result = m_m6844_channel[offset / 4].address & 0xff;
break;
// upper byte of counter
case 0x02:
case 0x06:
case 0x0a:
case 0x0e:
result = m_m6844_channel[offset / 4].counter >> 8;
break;
// lower byte of counter
case 0x03:
case 0x07:
case 0x0b:
case 0x0f:
result = m_m6844_channel[offset / 4].counter & 0xff;
break;
// channel control
case 0x10:
case 0x11:
case 0x12:
case 0x13:
result = m_m6844_channel[offset - 0x10].control;
// A read here clears the 'DMA end' flag of the
// associated channel.
if (!machine().side_effects_disabled())
{
m_m6844_channel[offset - 0x10].control &= ~0x80;
if (m_m6844_interrupt & 0x80)
m6844_update_interrupt();
}
break;
// priority control
case 0x14:
result = m_m6844_priority;
break;
// interrupt control
case 0x15:
result = m_m6844_interrupt;
break;
// chaining control
case 0x16:
result = m_m6844_chain;
break;
// 0x17-0x1f not used
default: break;
}
return result & 0xff;
}
//-------------------------------------------------
// write() handler
//-------------------------------------------------
void mc6844_device::write(offs_t offset, uint8_t data)
{
int i;
LOGSETUP("DMA write %02x: %02x\n", offset, data);
// switch off the offset we were given
switch (offset)
{
// upper byte of address
case 0x00:
case 0x04:
case 0x08:
case 0x0c:
LOGSETUP(" - upper address byte ch %d: %02x\n", offset / 4, data);
m_m6844_channel[offset / 4].address = (m_m6844_channel[offset / 4].address & 0xff) | (data << 8);
break;
// lower byte of address
case 0x01:
case 0x05:
case 0x09:
case 0x0d:
LOGSETUP(" - lower address byte ch %d: %02x\n", offset / 4, data);
m_m6844_channel[offset / 4].address = (m_m6844_channel[offset / 4].address & 0xff00) | (data & 0xff);
break;
// upper byte of counter
case 0x02:
case 0x06:
case 0x0a:
case 0x0e:
LOGSETUP(" - upper counter byte ch %d: %02x\n", offset / 4, data);
m_m6844_channel[offset / 4].counter = (m_m6844_channel[offset / 4].counter & 0xff) | (data << 8);
break;
// lower byte of counter
case 0x03:
case 0x07:
case 0x0b:
case 0x0f:
LOGSETUP(" - lower counter byte ch %d: %02x\n", offset / 4, data);
m_m6844_channel[offset / 4].counter = (m_m6844_channel[offset / 4].counter & 0xff00) | (data & 0xff);
break;
// channel control
case 0x10:
case 0x11:
case 0x12:
case 0x13:
LOGSETUP(" - control byte ch %d: %02x\n", offset / 4, data);
m_m6844_channel[offset - 0x10].control = (m_m6844_channel[offset - 0x10].control & 0xc0) | (data & 0x3f);
break;
// priority control
case 0x14:
LOGSETUP(" - priority byte: %02x\n", data);
m_m6844_priority = data;
// update each channel
for (i = 0; i < 4; i++)
{
// if we're going active...
if (!m_m6844_channel[i].active && (data & (1 << i)))
{
// mark us active
m_m6844_channel[i].active = 1;
// set the DMA busy bit and clear the DMA end bit
m_m6844_channel[i].control |= 0x40;
m_m6844_channel[i].control &= ~0x80;
// set the starting address, counter, and time
m_m6844_channel[i].start_address = m_m6844_channel[i].address;
m_m6844_channel[i].start_counter = m_m6844_channel[i].counter;
}
// if we're going inactive...
else if (m_m6844_channel[i].active && !(data & (1 << i)))
{
//mark us inactive
m_m6844_channel[i].active = 0;
}
}
break;
// interrupt control
case 0x15:
LOGSETUP(" - interrupt control: %02x\n", data);
m_m6844_interrupt = (m_m6844_interrupt & 0x80) | (data & 0x7f);
m6844_update_interrupt();
break;
// chaining control
case 0x16:
LOGSETUP(" - chaining control: %02x\n", data);
m_m6844_chain = data;
break;
// 0x17-0x1f not used
default: break;
}
LOGSTATE("Trigger(1)\n");
trigger(1);
}
//-------------------------------------------------
// m6844_update_interrupt()
//-------------------------------------------------
void mc6844_device::m6844_update_interrupt()
{
uint8_t interrupt = 0;
interrupt |= BIT(m_m6844_channel[0].control, 7) & BIT(m_m6844_interrupt, 0);
interrupt |= BIT(m_m6844_channel[1].control, 7) & BIT(m_m6844_interrupt, 1);
interrupt |= BIT(m_m6844_channel[2].control, 7) & BIT(m_m6844_interrupt, 2);
interrupt |= BIT(m_m6844_channel[3].control, 7) & BIT(m_m6844_interrupt, 3);
if (interrupt)
{
if (!(m_m6844_interrupt & 0x80))
{
// Set interrupt indication bit 7.
m_m6844_interrupt |= 0x80;
m_out_int_cb(ASSERT_LINE);
}
}
else
{
if (m_m6844_interrupt & 0x80)
{
// Clear interrupt indication bit 7.
m_m6844_interrupt &= 0x7f;
m_out_int_cb(CLEAR_LINE);
}
}
}

View File

@ -1,148 +0,0 @@
// license:BSD-3-Clause
// copyright-holders: Joakim Larsson Edström
/***************************************************************************
Motorola 6844 emulation
****************************************************************************
_____ _____
VSS 1 |* \_/ | 40 E
*CS / Tx AKBW 2 | | 39 *RESET
R / *W 3 | | 38 DGRNT
A0 4 | | 37 *DRQ1
A1 5 | | 36 *DRQ2
A2 6 | | 35 Tx AKA
A3 7 | | 34 *TX STB
A4 8 | | 33 *IRQ / *DEND
A5 9 | | 32 Tx RQ0
A6 10 | MC6844 | 31 Tx RQ1
A7 11 | | 30 Tx RQ2
A8 12 | | 29 Tx RQ3
A9 13 | | 28 D0
A10 14 | | 27 D1
A11 15 | | 26 D2
A12 16 | | 25 D3
A13 17 | | 24 D4
A14 18 | | 23 D5
A15 19 | | 22 D6
VCC 20 |_____________| 21 D7
***************************************************************************/
#ifndef MAME_MACHINE_MC6844_H
#define MAME_MACHINE_MC6844_H
#pragma once
//**************************************************************************
// INTERFACE CONFIGURATION MACROS
//**************************************************************************
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
// ======================> mc6844_device
class mc6844_device : public device_t, public device_execute_interface
{
public:
// construction/destruction
mc6844_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
auto out_int_callback() { return m_out_int_cb.bind(); }
auto out_txak_callback() { return m_out_txak_cb.bind(); }
auto out_drq1_callback() { return m_out_drq1_cb.bind(); }
auto out_drq2_callback() { return m_out_drq2_cb.bind(); }
auto in_memr_callback() { return m_in_memr_cb.bind(); }
auto out_memw_callback() { return m_out_memw_cb.bind(); }
// I/O operations
void write(offs_t offset, uint8_t data);
uint8_t read(offs_t offset);
template <unsigned CH> auto in_ior_callback() { return m_in_ior_cb[CH].bind(); }
template <unsigned CH> auto out_iow_callback() { return m_out_iow_cb[CH].bind(); }
template <unsigned CH> DECLARE_WRITE_LINE_MEMBER( dreq_w ) { dma_request(CH, state); }
DECLARE_WRITE_LINE_MEMBER( dgrnt_w ){ m_dgrnt = state; trigger(1); }
protected:
// device-level overrides
//virtual void device_validity_check(validity_checker &valid) const override;
virtual void device_resolve_objects() override;
virtual void device_start() override;
virtual void device_reset() override;
virtual void execute_run() override;
devcb_write_line m_out_int_cb;
devcb_write8 m_out_txak_cb;
devcb_write_line m_out_drq1_cb;
devcb_write_line m_out_drq2_cb;
devcb_read8 m_in_memr_cb;
devcb_write8 m_out_memw_cb;
devcb_read8 m_in_ior_cb[4];
devcb_write8 m_out_iow_cb[4];
/* channel_data structure holds info about each 6844 DMA channel */
struct m6844_channel_data
{
int active;
int address;
int counter;
// Channel control register.
// bit 0: Read / Write mode
// bit 1: Mode control B
// bit 2: Mode control A
// bit 3: Address up (0) / down (1).
// bit 4: Not used
// bit 5: Not used
// bit 6: Busy / Ready. Read only. Set when request
// made. Cleared when transfer completed.
// bit 7: DMA end flag. Read only? Set when transfer
// completed. Cleared when control register
// read. Sets IRQ.
// Mode control A,B: 0,0 Mode2; 0,1 Mode 3; 1,0 Mode 0;
// 1,1 Undefined.
uint8_t control;
int start_address;
int start_counter;
};
/* 6844 description */
m6844_channel_data m_m6844_channel[4];
uint8_t m_m6844_priority;
// Interrupt control register.
// Bit 0-3: channel interrupt enable, 1 enabled, 0 masked.
// Bit 4-6: unused
// Bit 7: Read only. Set to 1 when IRQ asserted. Clear when the
// control register associated with the channel that caused the
// interrut is read.
uint8_t m_m6844_interrupt;
uint8_t m_m6844_chain;
void m6844_update_interrupt();
// State machine
enum {
STATE_SI,
STATE_S0,
STATE_S1,
STATE_S2
};
int m_state;
int m_icount;
int m_current_channel;
int m_last_channel;
// input states
bool m_dgrnt;
bool m_dreq[4];
private:
void dma_request(int channel, int state);
};
// device type definition
DECLARE_DEVICE_TYPE(MC6844, mc6844_device)
#endif // MAME_MACHINE_MC6844_H

View File

@ -24,8 +24,6 @@
#include "mc6846.h"
//#define VERBOSE 1
//#define LOG_OUTPUT_STREAM std::cout
#include "logmacro.h"
@ -49,6 +47,7 @@ DEFINE_DEVICE_TYPE(MC6846, mc6846_device, "mc6846", "MC6846 Programmable Timer")
mc6846_device::mc6846_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, MC6846, tag, owner, clock),
m_out_port_cb(*this),
m_out_cp1_cb(*this),
m_out_cp2_cb(*this),
m_in_port_cb(*this),
m_out_cto_cb(*this),
@ -66,6 +65,7 @@ void mc6846_device::device_start()
m_one_shot = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(mc6846_device::timer_one_shot), this));
m_out_port_cb.resolve(); /* 8-bit output */
m_out_cp1_cb.resolve_safe(); /* 1-bit output */
m_out_cp2_cb.resolve(); /* 1-bit output */
/* CPU read from the outside through chip */
@ -354,7 +354,6 @@ READ8_MEMBER(mc6846_device::read)
WRITE8_MEMBER(mc6846_device::write)
{
switch ( offset )
{
case 0:

View File

@ -21,6 +21,7 @@ public:
auto out_port() { return m_out_port_cb.bind(); }
auto in_port() { return m_in_port_cb.bind(); }
auto cp1() { return m_out_cp1_cb.bind(); }
auto cp2() { return m_out_cp2_cb.bind(); }
auto cto() { return m_out_cto_cb.bind(); }
auto irq() { return m_irq_cb.bind(); }
@ -77,6 +78,7 @@ private:
/* CPU write to the outside through chip */
devcb_write8 m_out_port_cb; /* 8-bit output */
devcb_write_line m_out_cp1_cb; /* 1-bit output */
devcb_write_line m_out_cp2_cb; /* 1-bit output */
/* CPU read from the outside through chip */

View File

@ -22,6 +22,7 @@
TODO:
- CRC
- DMA mode
- loop mode
- status prioritization
- NRZI vs. NRZ coding
@ -33,18 +34,9 @@
#include "emu.h"
#include "mc6854.h"
#define LOG_SETUP ( 1U << 1 )
#define LOG_BITS ( 1U << 2 )
#define LOG_IRQ ( 1U << 3 )
//#define VERBOSE (LOG_IRQ | LOG_BITS | LOG_GENERAL | LOG_SETUP)
//#define LOG_OUTPUT_STREAM std::cout
//#define VERBOSE 1
#include "logmacro.h"
#define LOGSETUP(...) LOGMASKED(LOG_SETUP, __VA_ARGS__)
#define LOGBITS(...) LOGMASKED(LOG_BITS, __VA_ARGS__)
#define LOGIRQ(...) LOGMASKED(LOG_IRQ, __VA_ARGS__)
/******************* parameters ******************/
@ -74,9 +66,6 @@ constexpr unsigned mc6854_device::MAX_FRAME_LENGTH;
#define RIE ( m_cr1 & 2 ) /* interrupt enable */
#define TIE ( m_cr1 & 4 )
#define RDSR ( m_cr1 & 8 ) /* DMA mode */
#define TDSR ( m_cr1 & 0x10 )
#define DISCONTINUE ( m_cr1 & 0x20 ) /* discontinue received frame */
@ -142,8 +131,6 @@ DEFINE_DEVICE_TYPE(MC6854, mc6854_device, "mc6854", "Motorola MC6854 ADLC")
mc6854_device::mc6854_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, MC6854, tag, owner, clock),
m_out_irq_cb(*this),
m_out_rdsr_cb(*this),
m_out_tdsr_cb(*this),
m_out_txd_cb(*this),
m_out_frame_cb(*this),
m_out_rts_cb(*this),
@ -163,8 +150,6 @@ mc6854_device::mc6854_device(const machine_config &mconfig, const char *tag, dev
m_rreg(0),
m_rones(0),
m_rsize(0),
m_rxd(0),
m_rxc(0),
m_flen(0),
m_fpos(0)
{
@ -187,8 +172,6 @@ mc6854_device::mc6854_device(const machine_config &mconfig, const char *tag, dev
void mc6854_device::device_start()
{
m_out_irq_cb.resolve_safe();
m_out_rdsr_cb.resolve_safe();
m_out_tdsr_cb.resolve_safe();
m_out_txd_cb.resolve();
m_out_frame_cb.resolve();
m_out_rts_cb.resolve_safe();
@ -408,7 +391,6 @@ TIMER_CALLBACK_MEMBER(mc6854_device::tfifo_cb)
/* data underrun => abort */
logerror( "%f mc6854_tfifo_cb: FIFO underrun\n", machine().time().as_double() );
m_sr1 |= TU;
update_sr1();
m_tstate = 0;
send_bits( 0xffff, ABTEX ? 16 : 8, 0 );
m_flen = 0;
@ -532,10 +514,10 @@ void mc6854_device::rfifo_push( uint8_t d )
}
m_rsize -= blen;
update_sr1( );
}
void mc6854_device::rfifo_terminate( )
{
/* mark most recently pushed byte as the last one of the frame */
@ -544,7 +526,7 @@ void mc6854_device::rfifo_terminate( )
{
if ( m_rfifo[ i ] & 0x100 )
{
m_rfifo[ i ] |= 0x200;
m_tfifo[ i ] |= 0x200;
break;
}
@ -555,6 +537,7 @@ void mc6854_device::rfifo_terminate( )
}
/* CPU pops the FIFO */
uint8_t mc6854_device::rfifo_pop( )
{
@ -583,9 +566,70 @@ uint8_t mc6854_device::rfifo_pop( )
}
/* MC6854 makes fields from bits */
WRITE_LINE_MEMBER( mc6854_device::set_rx )
{
m_rxd = state;
int fieldlen = ( m_rstate < 6 ) ? 8 : RWL;
if ( RRESET || (m_sr2 & DCD) )
return;
if ( state )
{
m_rones++;
m_rreg = (m_rreg >> 1) | 0x80000000;
if ( m_rones >= 8 )
{
/* abort */
m_rstate = 0;
m_rsize = 0;
if ( m_rstate > 1 )
{
/* only in-frame abort */
m_sr2 |= RABT;
LOG( "%f mc6854_receive_bit: abort\n", machine().time().as_double() );
}
}
else
{
m_rsize++;
if ( m_rstate && m_rsize >= fieldlen + 24 )
rfifo_push( m_rreg );
}
}
else if ( m_rones == 5 )
{
/* discards '0' inserted after 5 '1' */
m_rones = 0;
return;
}
else if ( m_rones == 6 )
{
/* flag */
if ( FDSE )
m_sr1 |= FD;
if ( m_rstate > 1 )
{
/* end of frame */
m_rreg >>= 1;
m_rsize++;
if ( m_rsize >= fieldlen + 24 ) /* last field */
rfifo_push( m_rreg );
rfifo_terminate( );
LOG( "%f mc6854_receive_bit: end of frame\n", machine().time().as_double() );
}
m_rones = 0;
m_rstate = 1;
m_rsize = 0;
} else
{
m_rones = 0;
m_rreg >>= 1;
m_rsize++;
if ( m_rstate && m_rsize >= fieldlen + 24 )
rfifo_push( m_rreg );
}
}
@ -619,10 +663,7 @@ int mc6854_device::send_frame( uint8_t* data, int len )
}
memcpy( m_frame, data, len );
if ( FDSE )
{
m_sr1 |= FD;
update_sr1();
}
m_flen = len;
m_fpos = 0;
rfifo_push( m_frame[ m_fpos++ ] );
@ -648,7 +689,6 @@ WRITE_LINE_MEMBER( mc6854_device::set_cts )
m_sr1 |= CTS;
else
m_sr1 &= ~CTS;
update_sr1();
}
@ -675,7 +715,7 @@ void mc6854_device::update_sr2( )
m_sr2 |= RDA2;
if ( ! (m_rfifo[ FIFO_SIZE - 1 ] & 0x100) )
m_sr2 &= ~RDA2;
else if ( TWOBYTES && ! (m_rfifo[ FIFO_SIZE - 2 ] & 0x100) )
else if ( TWOBYTES && ! (m_tfifo[ FIFO_SIZE - 2 ] & 0x100) )
m_sr2 &= ~RDA2;
/* update AP */
@ -697,7 +737,7 @@ void mc6854_device::update_sr1( )
else
m_sr1 &= ~S2RQ;
/* update TDRA (always prioritized by CTS) */
/* update TRDA (always prioritized by CTS) */
if ( TRESET || ( m_sr1 & CTS ) )
m_sr1 &= ~TDRA;
else
@ -716,28 +756,18 @@ void mc6854_device::update_sr1( )
m_sr1 &= ~RDA;
/* update IRQ */
LOGIRQ("\nUpdate IRQ in: %d\n", (m_sr1 & IRQ) ? 1 : 0);
m_sr1 &= ~IRQ;
if ( RIE && (m_sr1 & (TU | TDRA) ) )
m_sr1 |= IRQ;
if ( TIE )
{
if ( m_sr1 & TU ) m_sr1 |= IRQ;
LOGIRQ(" - Update IRQ TU: %d\n", (m_sr1 & IRQ) ? 1 : 0);
if ( ( m_sr1 & TDRA ) && !TDSR ) m_sr1 |= IRQ; // TDRA will not cause interrupt if in DMA mode
LOGIRQ(" - Update IRQ TDRA: %d\n", (m_sr1 & IRQ) ? 1 : 0);
}
if ( RIE )
{
if ( m_sr1 & (S2RQ | CTS) ) m_sr1 |= IRQ;
LOGIRQ(" - Update IRQ S2RQ(%02x)|CTS(%d): %d\n", (m_sr2 & 0x7f), (m_sr1 & CTS) ? 1 : 0, (m_sr1 & IRQ) ? 1 : 0);
if ( ( m_sr1 & RDA ) && !RDSR ) m_sr1 |= IRQ; // RDA will not cause interrupt if in DMA mode
LOGIRQ(" - Update IRQ RDA(%d) && !RDSR(%d): %d\n", (m_sr1 & RDA) ? 1 : 0, RDSR ? 1 : 0, (m_sr1 & IRQ) ? 1 : 0);
if ( m_sr2 & (ERR | FV | DCD | OVRN | RABT | RIDLE | AP) ) m_sr1 |= IRQ;
LOGIRQ(" - Update IRQ ERR: %d\n", (m_sr1 & IRQ) ? 1 : 0);
if ( m_sr1 & (S2RQ | RDA | CTS) )
m_sr1 |= IRQ;
if ( m_sr2 & (ERR | FV | DCD | OVRN | RABT | RIDLE | AP) )
m_sr1 |= IRQ;
}
m_out_irq_cb((m_sr1 & IRQ) ? ASSERT_LINE : CLEAR_LINE);
m_out_rdsr_cb((m_sr1 & RDA) ? ASSERT_LINE : CLEAR_LINE);
m_out_tdsr_cb((m_sr1 & TDRA) ? ASSERT_LINE : CLEAR_LINE);
}
@ -747,7 +777,7 @@ uint8_t mc6854_device::read(offs_t offset)
switch ( offset )
{
case 0: /* status register 1 */
//update_sr1( );
update_sr1( );
LOG( "%f %s mc6854_r: get SR1=$%02X (rda=%i,s2rq=%i,fd=%i,cts=%i,tu=%i,tdra=%i,irq=%i)\n",
machine().time().as_double(), machine().describe_context(), m_sr1,
( m_sr1 & RDA) ? 1 : 0, ( m_sr1 & S2RQ) ? 1 : 0,
@ -757,7 +787,7 @@ uint8_t mc6854_device::read(offs_t offset)
return m_sr1;
case 1: /* status register 2 */
//update_sr2( );
update_sr2( );
LOG( "%f %s mc6854_r: get SR2=$%02X (ap=%i,fv=%i,ridle=%i,rabt=%i,err=%i,dcd=%i,ovrn=%i,rda2=%i)\n",
machine().time().as_double(), machine().describe_context(), m_sr2,
( m_sr2 & AP ) ? 1 : 0, ( m_sr2 & FV ) ? 1 : 0,
@ -772,7 +802,6 @@ uint8_t mc6854_device::read(offs_t offset)
uint8_t data = rfifo_pop( );
LOG( "%f %s mc6854_r: get data $%02X\n",
machine().time().as_double(), machine().describe_context(), data );
m_out_rdsr_cb(CLEAR_LINE); // Deactive DMA request line regardless of mode
return data;
}
@ -790,13 +819,15 @@ void mc6854_device::write(offs_t offset, uint8_t data)
{
case 0: /* control register 1 */
m_cr1 = data;
LOGSETUP( "%f %s mc6854_w: set CR1=$%02X (ac=%i,irq=%c%c,%sreset=%c%c)\n",
LOG( "%f %s mc6854_w: set CR1=$%02X (ac=%i,irq=%c%c,%sreset=%c%c)\n",
machine().time().as_double(), machine().describe_context(), m_cr1,
AC ? 1 : 0,
RIE ? 'r' : '-', TIE ? 't' : '-',
DISCONTINUE ? "discontinue," : "",
RRESET ? 'r' : '-', TRESET ? 't' : '-' );
if ( m_cr1 & 0xc )
logerror( "%s mc6854 DMA not handled (CR1=$%02X)\n",
machine().describe_context(), m_cr1 );
if ( DISCONTINUE )
{
/* abort receive FIFO but keeps shift register & synchro */
@ -810,14 +841,12 @@ void mc6854_device::write(offs_t offset, uint8_t data)
m_sr1 &= ~FD;
m_sr2 &= ~(AP | FV | RIDLE | RABT | ERR | OVRN | DCD);
if ( m_dcd ) m_sr2 |= DCD;
update_sr1( );
}
if ( TRESET )
{
tfifo_clear( );
m_sr1 &= ~(TU | TDRA | CTS);
if ( m_cts ) m_sr1 |= CTS;
update_sr1( );
}
break;
@ -826,7 +855,7 @@ void mc6854_device::write(offs_t offset, uint8_t data)
{
/* control register 3 */
m_cr3 = data;
LOGSETUP( "%f %s mc6854_w: set CR3=$%02X (lcf=%i,aex=%i,idl=%i,fdse=%i,loop=%i,tst=%i,dtr=%i)\n",
LOG( "%f %s mc6854_w: set CR3=$%02X (lcf=%i,aex=%i,idl=%i,fdse=%i,loop=%i,tst=%i,dtr=%i)\n",
machine().time().as_double(), machine().describe_context(), m_cr3,
LCF ? (CEX ? 16 : 8) : 0, AEX ? 1 : 0,
IDL0 ? 0 : 1, FDSE ? 1 : 0, LOOP ? 1 : 0,
@ -843,7 +872,7 @@ void mc6854_device::write(offs_t offset, uint8_t data)
{
/* control register 2 */
m_cr2 = data;
LOGSETUP( "%f %s mc6854_w: set CR2=$%02X (pse=%i,bytes=%i,fmidle=%i,%s,tlast=%i,clr=%c%c,rts=%i)\n",
LOG( "%f %s mc6854_w: set CR2=$%02X (pse=%i,bytes=%i,fmidle=%i,%s,tlast=%i,clr=%c%c,rts=%i)\n",
machine().time().as_double(), machine().describe_context(), m_cr2,
PSE ? 1 : 0, TWOBYTES ? 2 : 1, FMIDLE ? 1 : 0,
FCTDRA ? "fc" : "tdra", TLAST ? 1 : 0,
@ -860,7 +889,6 @@ void mc6854_device::write(offs_t offset, uint8_t data)
m_sr2 &= ~(AP | FV | RIDLE | RABT | ERR | OVRN | DCD);
if ( m_dcd )
m_sr2 |= DCD;
update_sr1( );
}
if ( data & 0x40 )
{
@ -868,7 +896,6 @@ void mc6854_device::write(offs_t offset, uint8_t data)
m_sr1 &= ~(TU | TDRA | CTS);
if ( m_cts )
m_sr1 |= CTS;
update_sr1( );
}
m_out_rts_cb( RTS ? 1 : 0 );
@ -876,7 +903,7 @@ void mc6854_device::write(offs_t offset, uint8_t data)
break;
case 2: /* transmitter data: continue data */
LOGSETUP( "%f %smc6854_w: push data=$%02X\n", machine().time().as_double(), machine().describe_context(), data );
LOG( "%f %smc6854_w: push data=$%02X\n", machine().time().as_double(), machine().describe_context(), data );
tfifo_push( data );
break;
@ -885,7 +912,7 @@ void mc6854_device::write(offs_t offset, uint8_t data)
{
/* control register 4 */
m_cr4 = data;
LOGSETUP( "%f %s mc6854_w: set CR4=$%02X (interframe=%i,tlen=%i,rlen=%i,%s%s)\n", machine().time().as_double(), machine().describe_context(), m_cr4,
LOG( "%f %s mc6854_w: set CR4=$%02X (interframe=%i,tlen=%i,rlen=%i,%s%s)\n", machine().time().as_double(), machine().describe_context(), m_cr4,
TWOINTER ? 2 : 1,
TWL, RWL,
ABT ? ( ABTEX ? "abort-ext," : "abort,") : "",
@ -900,7 +927,7 @@ void mc6854_device::write(offs_t offset, uint8_t data)
else
{
/* transmitter data: last data */
LOGSETUP( "%f %s mc6854_w: push last-data=$%02X\n", machine().time().as_double(), machine().describe_context(), data );
LOG( "%f %s mc6854_w: push last-data=$%02X\n", machine().time().as_double(), machine().describe_context(), data );
tfifo_push( data );
tfifo_terminate( );
}
@ -911,82 +938,9 @@ void mc6854_device::write(offs_t offset, uint8_t data)
}
}
inline bool mc6854_device::receive_allowed() const
{
return (!RRESET && !(m_sr2 & DCD));
}
/* MC6854 makes fields from bits */
WRITE_LINE_MEMBER( mc6854_device::rxc_w )
{
if (receive_allowed() && state && !m_rxc)
{
int fieldlen = ( m_rstate < 6 ) ? 8 : RWL;
if ( m_rxd )
{
LOGBITS("I ");
m_rones++;
m_rreg = (m_rreg >> 1) | 0x80000000;
if ( m_rones >= 8 )
{
/* abort */
m_rstate = 0;
m_rsize = 0;
if ( m_rstate > 1 )
{
/* only in-frame abort */
m_sr2 |= RABT;
LOG( "%f mc6854_receive_bit: abort\n", machine().time().as_double() );
}
}
else
{
m_rsize++;
if ( m_rstate && m_rsize >= fieldlen + 24 )
rfifo_push( m_rreg );
}
}
else if ( m_rones == 5 )
{
/* discards '0' inserted after 5 '1' */
LOGBITS("A zero is discarded\n");
m_rones = 0;
return;
}
else if ( m_rones == 6 )
{
/* flag */
if ( FDSE )
{
m_sr1 |= FD;
update_sr1( );
}
if ( m_rstate > 1 )
{
/* end of frame */
m_rreg >>= 1;
m_rsize++;
if ( m_rsize >= fieldlen + 24 ) /* last field */
rfifo_push( m_rreg );
rfifo_terminate( );
LOG( "%f mc6854_receive_bit: end of frame\n", machine().time().as_double() );
}
m_rones = 0;
m_rstate = 1;
m_rsize = 0;
} else
{
LOGBITS("O ");
m_rones = 0;
m_rreg >>= 1;
m_rsize++;
if ( m_rstate && m_rsize >= fieldlen + 24 )
rfifo_push( m_rreg );
}
}
m_rxc = state;
// TODO
}
WRITE_LINE_MEMBER( mc6854_device::txc_w )

View File

@ -23,19 +23,16 @@ public:
mc6854_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
auto out_irq_cb() { return m_out_irq_cb.bind(); }
auto out_rdsr_cb() { return m_out_rdsr_cb.bind(); }
auto out_tdsr_cb() { return m_out_tdsr_cb.bind(); }
auto out_txd_cb() { return m_out_txd_cb.bind(); }
auto out_rts_cb() { return m_out_rts_cb.bind(); }
auto out_dtr_cb() { return m_out_dtr_cb.bind(); }
auto out_irq_cb() { return m_out_irq_cb.bind(); }
auto out_txd_cb() { return m_out_txd_cb.bind(); }
auto out_rts_cb() { return m_out_rts_cb.bind(); }
auto out_dtr_cb() { return m_out_dtr_cb.bind(); }
template <typename... T> void set_out_frame_callback(T &&... args) { m_out_frame_cb.set(std::forward<T>(args)...); }
/* interface to CPU via address/data bus*/
uint8_t read(offs_t offset);
void write(offs_t offset, uint8_t data);
uint8_t dma_r(){ return read(2); }
/* low-level, bit-based interface */
DECLARE_WRITE_LINE_MEMBER( set_rx );
@ -55,15 +52,12 @@ protected:
// device-level overrides
virtual void device_start() override;
virtual void device_reset() override;
bool receive_allowed() const;
private:
static constexpr unsigned FIFO_SIZE = 3; // hardcoded size of the 6854 FIFO (this is a hardware limit)
// internal state
devcb_write_line m_out_irq_cb; /* interrupt request */
devcb_write_line m_out_rdsr_cb; /* Rx fifo DMA request */
devcb_write_line m_out_tdsr_cb; /* Tx fifo DMA request */
/* low-level, bit-based interface */
devcb_write_line m_out_txd_cb; /* transmit bit */
@ -93,8 +87,6 @@ private:
uint8_t m_rones; /* count '1 bits */
uint8_t m_rsize; /* bits in the shift register */
uint16_t m_rfifo[FIFO_SIZE]; /* X x 8-bit FIFO + full & addr marker bits */
bool m_rxd;
bool m_rxc;
/* frame-based interface*/
uint8_t m_frame[MAX_FRAME_LENGTH];
@ -140,7 +132,6 @@ DECLARE_DEVICE_TYPE(MC6854, mc6854_device)
The frame-based interface is higher-level and faster.
It passes bytes directly from one end to the other without bothering with
the actual bit-encoding, synchronization, and CRC.
Once completed, a frame is sent through out_frame. Aborted frames are not
transmitted at all. No start flag, stop flag, or crc bits are transmitted.
send_frame makes a frame available to the CPU through the 6854 (it may

View File

@ -12,12 +12,10 @@
#include "plaparse.h"
#define LOG_TERMS (1 << 0U)
//#define VERBOSE (LOG_TERMS)
//#define LOG_OUTPUT_STREAM std::cout
#include "logmacro.h"
DEFINE_DEVICE_TYPE(PLA, pla_device, "pla", "PLA")
DEFINE_DEVICE_TYPE(PLS100, pls100_device, "pls100", "82S100-series PLA")
DEFINE_DEVICE_TYPE(MOS8721, mos8721_device, "mos8721", "MOS 8721 PLA")
@ -125,8 +123,6 @@ void pla_device::parse_fusemap()
return;
}
LOGMASKED(LOG_TERMS, "PLA read and parsed, %d fuses in %s format\n", jed.numfuses, jed.binfmt == MAXLOADER ? "Maxloader" : "DataIO" );
// parse it
uint32_t fusenum = 0;
@ -139,21 +135,11 @@ void pla_device::parse_fusemap()
for (int i = 0; i < m_inputs; i++)
{
if (jed.binfmt == MAXLOADER)
{
term->and_mask |= (uint64_t)jed_get_fuse(&jed, fusenum++) << (i + 32); // complement
term->and_mask |= (uint64_t)jed_get_fuse(&jed, fusenum++) << i; // true
}
else if (jed.binfmt == DATAIO)
{
term->and_mask |= (uint64_t)jed_get_fuse(&jed, fusenum++) << i; // true
term->and_mask |= (uint64_t)jed_get_fuse(&jed, fusenum++) << (i + 32); // complement
}
else
{
logerror("PLA parser: Unknown JED format\n");
break;
}
// complement
term->and_mask |= (uint64_t)jed_get_fuse(&jed, fusenum++) << (i + 32);
// true
term->and_mask |= (uint64_t)jed_get_fuse(&jed, fusenum++) << i;
}
// OR mask

View File

@ -391,24 +391,9 @@ int jedbin_parse(const void *data, size_t length, jed_data *result)
/* first unpack the number of fuses */
result->numfuses = (cursrc[0] << 24) | (cursrc[1] << 16) | (cursrc[2] << 8) | cursrc[3];
cursrc += 4;
if (result->numfuses == 0 || result->numfuses > JED_MAX_FUSES)
return JEDERR_INVALID_DATA;
/* Detect DataIO binary format and prepare for conversion. This transformation is based on observation of an 82S100 dump */
if (result->numfuses == ((cursrc[0] << 24) | (cursrc[1] << 16) | (cursrc[2] << 8) | cursrc[3]))
{
result->numfuses = (result->numfuses - 9) * 8; // Double 32 bit byte file size header + trailing byte to Single 32 byte fuse count
cursrc = cursrc + 4; // Adjust start of buffer, trailing byte will not be copied below
result->binfmt = DATAIO; // DataIO also has swapped inverted/non-inverted line fuses so remember origin
if (LOG_PARSE) printf("DATAIO format detected\n");
}
else
{
result->binfmt = MAXLOADER; // This is the old format just set for completeness.
if (LOG_PARSE) printf("MAXLOADER format detected\n");
}
/* now make sure we have enough data in the source */
if (length < 4 + (result->numfuses + 7) / 8)
return JEDERR_INVALID_DATA;

View File

@ -29,9 +29,7 @@
#define JEDERR_BAD_XMIT_SUM 2
#define JEDERR_BAD_FUSE_SUM 3
/* binary file formats */
#define MAXLOADER 0
#define DATAIO 1
/***************************************************************************
TYPE DEFINITIONS
@ -39,9 +37,8 @@
struct jed_data
{
uint32_t numfuses; /* number of defined fuses */
uint8_t fusemap[JED_MAX_FUSES / 8]; /* array of bit-packed data */
uint8_t binfmt; /* file format MAXLOADER or DATAIO */
uint32_t numfuses; /* number of defined fuses */
uint8_t fusemap[JED_MAX_FUSES / 8];/* array of bit-packed data */
};

View File

@ -5,7 +5,7 @@
Alfaskop 41 series
This driver is a part of a revivel project for Alfaskop 41 series where
no known working system exists today because of its distributed nature.
no known working system exists today because of the distributed nature.
All parts network boots over SS3 (SDLC) from a Floppy Disk unit and nothing
works unless there is a floppy in that unit. These floppies are rare and
many parts have been discarded because they are useless stand alone.
@ -25,31 +25,18 @@ Dansk Datahistorisk Forening - http://datamuseum.dk/
#include "cpu/m6800/m6800.h"
#include "machine/6850acia.h"
#include "machine/6821pia.h"
#include "machine/mc6854.h"
#include "machine/mc6844.h"
#include "machine/pla.h"
#include "video/mc6845.h"
#include "screen.h"
#include "machine/input_merger.h"
#include "machine/output_latch.h"
#include "machine/alfaskop_s41_kb.h"
//#include "bus/rs232/rs232.h"
#include "machine/clock.h"
//#include "machine/clock.h"
#define LOG_IO (1U << 1)
#define LOG_NVRAM (1U << 2)
#define LOG_MIC (1U << 3)
#define LOG_DIA (1U << 4)
#define LOG_DMA (1U << 5)
#define LOG_IRQ (1U << 6)
#define LOG_ADLC (1U << 7)
#define LOG_KBD (1U << 8)
#define LOG_AM (1U << 9)
#define LOG_LEDS (1U << 10)
#define LOG_BITS (1U << 11)
//#define VERBOSE (LOG_MIC)
//#define VERBOSE (LOG_IO|LOG_NVRAM|LOG_MIC|LOG_DIA)
//#define LOG_OUTPUT_STREAM std::cout
#include "logmacro.h"
@ -58,15 +45,6 @@ Dansk Datahistorisk Forening - http://datamuseum.dk/
#define LOGNVRAM(...) LOGMASKED(LOG_NVRAM, __VA_ARGS__)
#define LOGMIC(...) LOGMASKED(LOG_MIC, __VA_ARGS__)
#define LOGDIA(...) LOGMASKED(LOG_DIA, __VA_ARGS__)
#define LOGDMA(...) LOGMASKED(LOG_DMA, __VA_ARGS__)
#define LOGIRQ(...) LOGMASKED(LOG_IRQ, __VA_ARGS__)
#define LOGADLC(...) LOGMASKED(LOG_ADLC, __VA_ARGS__)
#define LOGKBD(...) LOGMASKED(LOG_KBD, __VA_ARGS__)
#define LOGAM(...) LOGMASKED(LOG_AM, __VA_ARGS__)
#define LOGLEDS(...) LOGMASKED(LOG_LEDS, __VA_ARGS__)
#define LOGBITS(...) LOGMASKED(LOG_BITS, __VA_ARGS__)
#define PLA1_TAG "ic50"
class alfaskop4110_state : public driver_device
{
@ -74,96 +52,30 @@ public:
alfaskop4110_state(const machine_config &mconfig, device_type type, const char *tag)
: driver_device(mconfig, type, tag)
, m_maincpu(*this, "maincpu")
, m_kbd_acia(*this, "kbd_acia")
, m_mic_pia(*this, "mic_pia")
, m_dia_pia(*this, "dia_pia")
, m_kbdacia(*this, "kbdacia")
, m_micpia(*this, "micpia")
, m_diapia(*this, "diapia")
, m_crtc(*this, "crtc")
, m_screen(*this, "screen")
, m_vram(*this, "vram")
, m_pla(*this, PLA1_TAG)
, m_kbd(*this, "keyboard")
, m_chargen(*this, "chargen")
, m_tia_adlc(*this, "tia_adlc")
, m_tia_dma(*this, "tia_dma")
, m_irq(0)
, m_imsk(0)
{ }
void alfaskop4110(machine_config &config);
private:
virtual void machine_start() override;
virtual void machine_reset() override;
void mem_map(address_map &map);
required_device<cpu_device> m_maincpu;
required_device<acia6850_device> m_kbd_acia;
required_device<pia6821_device> m_mic_pia;
required_device<pia6821_device> m_dia_pia;
required_device<acia6850_device> m_kbdacia;
required_device<pia6821_device> m_micpia;
required_device<pia6821_device> m_diapia;
required_device<mc6845_device> m_crtc;
required_device<screen_device> m_screen;
required_shared_ptr<uint8_t> m_vram;
required_device<pls100_device> m_pla;
required_device<alfaskop_s41_keyboard_device> m_kbd;
/* Video controller */
required_region_ptr<uint8_t> m_chargen;
MC6845_UPDATE_ROW(crtc_update_row);
/* TIA */
required_device<mc6854_device> m_tia_adlc;
required_device<mc6844_device> m_tia_dma;
/* Interrupt handling */
template <unsigned N> DECLARE_WRITE_LINE_MEMBER(irq_w);
uint8_t m_irq;
uint8_t m_imsk;
/* Kbd communications */
uint8_t m_txd;
/* Debug stuff */
/* Timer */
enum
{
TIMER_POLL_START,
TIMER_POLL_BIT
};
void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
// DEBUG stuff, will be removed when hooked up towards remote peer
#if 1
/* zero extended SDLC poll message frame to feed into receiver as a test
0 1 1 1 1 1 1 0 ; opening flag 0x7e
0 0 0 0 0 0 0 0 ; 0x00
1 1 1 1 1 0 1 1 1 ; 0xff <- a zero needs to be inserted, done by test code
0 0 0 0 0 0 1 1 ; 0xc0
0 0 0 0 0 1 0 1 ; 0xa0
1 0 1 1 0 0 0 1 ; CRC 0x8d
1 0 1 0 1 0 1 0 ; CRC 0x55
0 1 1 1 1 1 1 0 ; closing flag 0x7e
*/
uint8_t txBuf[10] = {0x7e, 0x00, 0xff, 0xc0, 0xa0, 0x8d, 0x55, 0x7e};
#else // Alternative poll message body wih faulty CRC, CRC isn't checked yet by the ADLC
/* zero extended SDLC poll message frame to feed into receiver as a test
0 1 1 1 1 1 1 0 ; opening flag 0x7e
0 0 0 0 0 0 0 0 ; 0x00
0 0 0 0 0 0 0 0 ; 0x00
1 1 1 1 1 0 1 1 0 ; 0xfe <- a zero needs to be inserted, done by test code
1 1 1 0 1 0 0 1 ; 0xe9
1 0 1 1 0 0 0 1 ; CRC 0x8d - wrong
1 0 1 0 1 0 1 0 ; CRC 0x55 - wrong
0 1 1 1 1 1 1 0 ; closing flag 0x7e
*/
uint8_t txBuf[10] = {0x7e, 0x00, 0x00, 0xfe, 0xe9, 0x8d, 0x55, 0x7e};
#endif
int index = 0;
int pos = 0;
int ones = 0;
bool flank = false;
};
class alfaskop4120_state : public driver_device
@ -172,8 +84,8 @@ public:
alfaskop4120_state(const machine_config &mconfig, device_type type, const char *tag)
: driver_device(mconfig, type, tag)
, m_maincpu(*this, "maincpu")
, m_mic_pia(*this, "mic_pia")
, m_fdapia(*this, "dia_pia")
, m_micpia(*this, "micpia")
, m_fdapia(*this, "diapia")
{ }
void alfaskop4120(machine_config &config);
@ -181,7 +93,7 @@ private:
void mem_map(address_map &map);
required_device<cpu_device> m_maincpu;
required_device<pia6821_device> m_mic_pia;
required_device<pia6821_device> m_micpia;
required_device<pia6821_device> m_fdapia;
};
@ -191,7 +103,7 @@ public:
alfaskop4101_state(const machine_config &mconfig, device_type type, const char *tag)
: driver_device(mconfig, type, tag)
, m_maincpu(*this, "maincpu")
, m_mic_pia(*this, "mic_pia")
, m_micpia(*this, "micpia")
{ }
void alfaskop4101(machine_config &config);
@ -199,77 +111,31 @@ private:
void mem_map(address_map &map);
required_device<cpu_device> m_maincpu;
required_device<pia6821_device> m_mic_pia;
required_device<pia6821_device> m_micpia;
};
void alfaskop4110_state::mem_map(address_map &map)
{
map.unmap_value_high();
map(0x0000, 0x7fff).ram();
map(0x7800, 0x7fff).ram().share(m_vram); // TODO: Video RAM base address is configurable via NVRAM - this is the default
map(0x7800, 0x7fff).ram().share(m_vram);
map(0x8000, 0xefff).ram();
// NVRAM
map(0xf600, 0xf6ff).lrw8(NAME([this](offs_t offset) -> uint8_t
{
LOGNVRAM("nvram_r %04x: %02x\n", offset, 0); return (uint8_t) 0;
}),
NAME([this](offs_t offset, uint8_t data)
{
LOGNVRAM("nvram_w %04x: %02x\n", offset, data);
}));
// TIA board
map(0xf700, 0xf71f).mirror(0x00).lrw8(NAME([this](offs_t offset) -> uint8_t { LOGDMA("TIA DMA_r %04x: %02x\n", offset, 0); return m_tia_dma->read(offset); }),
NAME([this](offs_t offset, uint8_t data) { LOGDMA("TIA DMA_w %04x: %02x\n", offset, data); m_tia_dma->write(offset, data); }));
map(0xf720, 0xf723).mirror(0x04).lrw8(NAME([this](offs_t offset) -> uint8_t { LOGADLC("TIA ADLC_r %04x: %02x\n", offset, 0); return m_tia_adlc->read(offset); }),
NAME([this](offs_t offset, uint8_t data) { LOGADLC("TIA ADLC_w %04x: %02x\n", offset, data); m_tia_adlc->write(offset, data); }));
// Main PCB
map(0xf600, 0xf6ff).lrw8(NAME([this](offs_t offset) -> uint8_t { LOGNVRAM("nvram_r %04x: %02x\n", offset, 0); return (uint8_t) 0; }),// TODO: Move to MRO board
NAME( [this](offs_t offset, uint8_t data) { LOGNVRAM("nvram_w %04x: %02x\n", offset, data); }));
map(0xf7d9, 0xf7d9).mirror(0x06).lrw8(NAME([this](offs_t offset) -> uint8_t { LOGIO("CRTC reg r %04x: %02x\n", offset, 0); return m_crtc->register_r(); }),
NAME([this](offs_t offset, uint8_t data) { LOGIO("CRTC reg w %04x: %02x\n", offset, data); m_crtc->register_w(data);}));
NAME([this](offs_t offset, uint8_t data) { LOGIO("CRTC reg w %04x: %02x\n", offset, data); m_crtc->register_w(data);}));
map(0xf7d8, 0xf7d8).mirror(0x06).lw8(NAME([this](offs_t offset, uint8_t data) { LOGIO("CRTC adr w %04x: %02x\n", offset, data); m_crtc->address_w(data); }));
map(0xf7d0, 0xf7d3).mirror(0x04).lrw8(NAME([this](offs_t offset) -> uint8_t { LOGDIA("DIA pia_r %04x: %02x\n", offset, 0); return m_dia_pia->read(offset & 3); }),
NAME([this](offs_t offset, uint8_t data) { LOGDIA("DIA pia_w %04x: %02x\n", offset, data); m_dia_pia->write(offset & 3, data); }));
map(0xf7c4, 0xf7c7).mirror(0x00).lrw8(NAME([this](offs_t offset) -> uint8_t { uint8_t tmp = m_mic_pia->read(offset & 3); LOGMIC("\nMIC pia_r %04x: %02x\n", offset, tmp); return tmp; }),
NAME([this](offs_t offset, uint8_t data) { LOGMIC("\nMIC pia_w %04x: %02x\n", offset, data); m_mic_pia->write(offset & 3, data); }));
map(0xf7c0, 0xf7c1).mirror(0x02).lrw8(NAME([this](offs_t offset) -> uint8_t { LOGKBD("KBD acia_r %04x: %02x\n", offset, 0); return m_kbd_acia->read(offset & 1); }),
NAME([this](offs_t offset, uint8_t data) { LOGKBD("KBD acia_w %04x: %02x\n", offset, data); m_kbd_acia->write(offset & 1, data); }));
map(0xf7d0, 0xf7d3).mirror(0x04).lrw8(NAME([this](offs_t offset) -> uint8_t { LOGIO("DIA pia_r %04x: %02x\n", offset, 0); return m_diapia->read(offset & 3); }),
NAME([this](offs_t offset, uint8_t data) { LOGIO("DIA pia_w %04x: %02x\n", offset, data); m_diapia->write(offset & 3, data); }));
map(0xf7c4, 0xf7c7).mirror(0x00).lrw8(NAME([this](offs_t offset) -> uint8_t { LOGIO("MIC pia_r %04x: %02x\n", offset, 0); return m_micpia->read(offset & 3); }),
NAME( [this](offs_t offset, uint8_t data) { LOGIO("MIC pia_w %04x: %02x\n", offset, data); m_micpia->write(offset & 3, data); }));
map(0xf7c0, 0xf7c1).mirror(0x02).lrw8(NAME([this](offs_t offset) -> uint8_t { LOGIO("KBD acia_r %04x: %02x\n", offset, 0); return m_kbdacia->read(offset & 1); }),
NAME( [this](offs_t offset, uint8_t data) { LOGIO("KBD acia_w %04x: %02x\n", offset, data); m_kbdacia->write(offset & 1, data); }));
map(0xf7fc, 0xf7fc).mirror(0x00).lr8(NAME([this](offs_t offset) -> uint8_t { LOGIO("Address Switch 0-7\n"); return 0; }));
map(0xf7fc, 0xf7fc).mirror(0x00).lr8(NAME([this](offs_t offset) -> uint8_t { LOGIO("Address Switch 0-7\n"); return 0; }));
map(0xf800, 0xffe7).rom().region("roms", 0);
// IRQ mask setting
map(0xffe8, 0xfff7).rom().lrw8( NAME([this](offs_t offset) -> uint8_t
{
if (!machine().side_effects_disabled()) LOGAM("AMSK read set %04x\n", offset >> 1);
m_imsk = (offset >> 1) & 7;
return ((uint8_t *) memregion("roms")->base() + 0x7e8)[offset];
}),
NAME([this](offs_t offset, uint8_t data)
{
if (!machine().side_effects_disabled()) LOGAM("AMSK write set %04x\n", offset);
m_imsk = (offset >> 1) & 7;
}));
// Address modification
map(0xfff8, 0xfff9).rom().lrw8( NAME([this](offs_t offset) -> uint8_t
{
uint16_t ploffs = (~m_irq & 0xff) | ((m_imsk & 0x07) << 8) | 0x000 | (0x18 << 11);
uint8_t tmp = ((uint8_t *) memregion("roms")->base())[0x7e0 | offset | ((m_pla->read(ploffs) & 0xf0) >> 3)];
if (!machine().side_effects_disabled())
{
LOGAM("AMOD read %04x: %02x\n", offset, tmp);
LOGAM("AMOD pla read %04x: %02x ==> %04x\n", ploffs, m_pla->read(ploffs), (0xffe0 | offset | ((m_pla->read(ploffs) & 0xf0) >> 3)));
}
return tmp;
}),
NAME([this](offs_t offset, uint8_t data) // TODO: Check what a write does if anything
{
if (!machine().side_effects_disabled()) LOGAM("AMOD write %04x\n", offset);
}));
map(0xfffa, 0xffff).rom().region("roms", 0x7fa);
map(0xf800, 0xffff).rom().region("roms", 0);
}
void alfaskop4120_state::mem_map(address_map &map)
@ -279,9 +145,9 @@ void alfaskop4120_state::mem_map(address_map &map)
map(0xf600, 0xf6ff).lrw8(NAME([this](offs_t offset) -> uint8_t { LOGNVRAM("nvram_r %04x: %02x\n", offset, 0); return (uint8_t) 0; }), // TODO: Move to MRO board
NAME([this](offs_t offset, uint8_t data) { LOGNVRAM("nvram_w %04x: %02x\n", offset, data); }));
map(0xf740, 0xf743).mirror(0x0c).lrw8(NAME([this](offs_t offset) -> uint8_t { LOGIO("FDA pia_r %04x: %02x\n", offset, 0); return m_fdapia->read(offset & 3); }),
NAME([this](offs_t offset, uint8_t data) { LOGIO("FDA pia_w %04x: %02x\n", offset, data); m_fdapia->write(offset & 3, data); }));
map(0xf7c4, 0xf7c7).mirror(0x00).lrw8(NAME([this](offs_t offset) -> uint8_t { LOGMIC("MIC pia_r %04x: %02x\n", offset, 0); return m_mic_pia->read(offset & 3); }),
NAME([this](offs_t offset, uint8_t data) { LOGMIC("MIC pia_w %04x: %02x\n", offset, data); m_mic_pia->write(offset & 3, data); }));
NAME([this](offs_t offset, uint8_t data) { LOGIO("FDA pia_w %04x: %02x\n", offset, data); m_fdapia->write(offset & 3, data); }));
map(0xf7c4, 0xf7c7).mirror(0x00).lrw8(NAME([this](offs_t offset) -> uint8_t { LOGIO("MIC pia_r %04x: %02x\n", offset, 0); return m_micpia->read(offset & 3); }),
NAME([this](offs_t offset, uint8_t data) { LOGIO("MIC pia_w %04x: %02x\n", offset, data); m_micpia->write(offset & 3, data); }));
map(0xf800, 0xffff).rom().region("roms", 0);
}
@ -291,8 +157,8 @@ void alfaskop4101_state::mem_map(address_map &map)
map(0x0000, 0xefff).ram();
map(0xf600, 0xf6ff).lrw8(NAME([this](offs_t offset) -> uint8_t { LOGNVRAM("nvram_r %04x: %02x\n", offset, 0); return (uint8_t) 0; }),
NAME([this](offs_t offset, uint8_t data) { LOGNVRAM("nvram_w %04x: %02x\n", offset, data); }));
map(0xf7c4, 0xf7c7).mirror(0x00).lrw8(NAME([this](offs_t offset) -> uint8_t { LOGMIC("MIC pia_r %04x: %02x\n", offset, 0); return m_mic_pia->read(offset & 3); }),
NAME([this](offs_t offset, uint8_t data) { LOGMIC("MIC pia_w %04x: %02x\n", offset, data); m_mic_pia->write(offset & 3, data); }));
map(0xf7c4, 0xf7c7).mirror(0x00).lrw8(NAME([this](offs_t offset) -> uint8_t { LOGIO("MIC pia_r %04x: %02x\n", offset, 0); return m_micpia->read(offset & 3); }),
NAME([this](offs_t offset, uint8_t data) { LOGIO("MIC pia_w %04x: %02x\n", offset, data); m_micpia->write(offset & 3, data); }));
map(0xf800, 0xffff).rom().region("roms", 0);
}
@ -306,14 +172,6 @@ INPUT_PORTS_END
static INPUT_PORTS_START( alfaskop4101 )
INPUT_PORTS_END
/* Interrupt handling - vector address modifyer, irq prioritizer and irq mask */
template <unsigned N> WRITE_LINE_MEMBER( alfaskop4110_state::irq_w )
{
m_irq = (m_irq & ~(1 << N)) | ((state ? 1 : 0) << N);
LOGIRQ("4110 IRQ %d: %d ==> %02x\n", N, state, m_irq);
m_maincpu->set_input_line(M6800_IRQ_LINE, state);
}
/* Simplified chargen, no attributes or special formats/features yet */
MC6845_UPDATE_ROW( alfaskop4110_state::crtc_update_row )
{
@ -339,256 +197,38 @@ void alfaskop4110_state::alfaskop4110(machine_config &config)
M6800(config, m_maincpu, XTAL(19'170'000) / 18); // Verified from service manual
m_maincpu->set_addrmap(AS_PROGRAM, &alfaskop4110_state::mem_map);
// TTL-level serial keyboard callback
ALFASKOP_S41_KB(config, m_kbd);
m_kbd->txd_cb().set([this](bool state)
{
LOGBITS("KBD->4110: %d\n", state);
m_kbd_acia->write_rxd(state);
});
m_kbd->leds_cb().set([this] (uint8_t data)
{
LOGLEDS("LEDS: write %02x to LEDs\n", data);
});
/* Interrupt controller and address modifier PLA */
/*
* 82S100 data sheet
* -----------------
*
* The 82S100 is a bipolar, fuse-link programmable logic array. It uses the
* standard AND/OR/invert architecture to directly implement custom
* um-of-product logic equations.
*
* Each device consists of 16 dedicated inputs and 8 dedicated outputs. Each
* output is capable of being actively controlled by any or all of the 48
* product terms. The true, complement, or don't care condition of each of the
* 16 inputs ANDed together comprise one P-Term. All 48 P-Terms are then OR-d
* to each output. The user must then only select which P-Terms will activate
* an output by disconnecting terms which do not affect the output. In addition,
* each output can be fused as active high or active low.
*
* The 82S100 is fully TTL compatible and includes chip-enable control for
* expansion of input variables and output inhibit. It features three state
* outputs.
*
* Field programmable Ni-Cr links
* 16 inputs
* 8 outputs
* 48 product terms
* Commercial verion - N82S100 - 50ns max address access time
* Power dissipation - 600mW typ
* Input loading - 100uA max
* Chip enable input
* Three state outputs
*
*
*/
/* _____ _____
* nc FE 1 |* \_/ | 28 Vcc
* IRQ7 I7 2 | | 27 I8 mask 1
* IRQ6 I6 3 | | 26 I9 mask 2
* IRQ5 I5 4 | | 25 I10 mask 3
* IRQ4 I4 5 | | 24 I11 Address &== 1111 1111 111x xxxx
* IRQ3 I3 6 | 82S100 | 23 I12 AI 1 A1
* IRQ2 I2 7 | | 22 I13 AI 2 A2
* IRQ1 I1 8 | IC50 | 21 I14 AI 3 A3
* IRQ0 I0 9 | | 20 I15 AI 4 A4
* P4 F7 10 | Interrupt | 19 _CE
* mask P3 F6 11 | Controller | 18 F0 IRQ
* mask P2 F5 12 | PLA | 17 F1 mask register
* mask P1 F4 13 | | 16 F2 interrupt latch
* GND 14 |_____________| 15 F3 nc
*/
PLS100(config, m_pla);
MC6845(config, m_crtc, XTAL(19'170'000) / 9);
m_crtc->set_screen("screen");
m_crtc->set_show_border_area(false);
m_crtc->set_char_width(8);
m_crtc->set_update_row_callback(FUNC(alfaskop4110_state::crtc_update_row));
// VSYNC should goto IRQ1 through some logic involving MIC PIA CRA bits 0 ( 1 == enable) & 1 (1 == positive edge)
//m_crtc->out_vsync_callback().set(FUNC(alfaskop4110_state::crtc_vsync);
//m_crtc->out_vsync_callback().set([this](bool state) { LOGIRQ("CRTC VSYNC: %d\n", state); });
//m_crtc->out_vsync_callback().set("irq1", FUNC(input_merger_device::in_w<1>));
SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
m_screen->set_raw(19'170'000, 80 * 8, 0, 80 * 8, 400, 0, 400);
m_screen->set_screen_update("crtc", FUNC(mc6845_device::screen_update));
PIA6821(config, m_mic_pia, 0); // Main board PIA
m_mic_pia->readcb1_handler().set([this](offs_t offset) -> uint8_t { LOGMIC("<-MIC PIA: CB1 read\n"); return 0;});
m_mic_pia->cb2_handler().set([this](offs_t offset, uint8_t data) { LOGMIC("->MIC PIA: CB2 write %d\n", data); });
PIA6821(config, m_micpia, 0); // Main board PIA
m_micpia->readcb1_handler().set([this](offs_t offset) -> uint8_t { LOGMIC("MIC PIA: CB1_r\n"); return 0;});
m_micpia->cb2_handler().set([this](offs_t offset, uint8_t data) { LOGMIC("MIC PIA: CB2_w\n"); });
m_micpia->writepa_handler().set([this](offs_t offset, uint8_t data) { LOGMIC("MIC PIA: PA_w\n"); });
m_micpia->writepb_handler().set([this](offs_t offset, uint8_t data) { LOGMIC("MIC PIA: PB_w\n"); });
m_micpia->readpa_handler().set([this](offs_t offset) -> uint8_t { LOGMIC("MIC PIA: PA_r\n"); return 0;});
m_micpia->readpb_handler().set([this](offs_t offset) -> uint8_t { LOGMIC("MIC PIA: PB_r\n"); return 0;});
m_micpia->readca1_handler().set([this](offs_t offset) -> uint8_t { LOGMIC("MIC PIA: CA1_r\n"); return 0;});
m_micpia->readca2_handler().set([this](offs_t offset) -> uint8_t { LOGMIC("MIC PIA: CA2_r\n"); return 0;});
/*
* MIC PIA interface
*
* Port A (DDRA=0x7a)
* 0 - PA0 input - not used
* 1 - PA1 output - KB reset P11 pin 23 at connector 1 == KB reset 0 == no KB reset
* 2 - PA2 input - MCP test mode 1 == no test mode 0 == in test mode,
* 3 - PA3 output - not used (in DTC)
* 4 - PA4 output - not used (in DTC)
* 5 - PA5 output - Interrupt enable 1 == Int. out on P1:7 0 == no Int. out
* 6 - PA6 output - I4 latch enable 1 == I4 will be latched 0 == no I4 latch
* 7 - PA7 input - Button/MCP NMI 1 == NMI from DU button 0 == NMI from MCP P4:1=low
* Note: At initialization a KB reset pulse will be sent as DDRA contains all zeros: PA I functions as a
* high impedance input: "active level" for KB reset generation.
*
* Port B (DDRB=0xff)
* 0 - PB0 output - Reset PC-error 1 == Reset PC error FF 0 == Memory PC used
* or PC not used
* 1 - PB1 output - VMAX/VMA 1 MPU 1 == VMAX gen by MPU 0 == VMA 1 gen by MPU
* 2 - PB2 output - VMAX/VMA 1 DMA 1 == VMAX gen by DMA 0 == VMA 1 gen by DMA
* 3 - PB3 output - Display Memory 1 == 4KB Display Memory 0 == 8KB Display Memory
* 4 - PB4 output - Option Character Generator 1 == Enabled to MIC bus 0 == Disabled from MIC bus
* 5 - PB5 output - MPU Addr 1 == Mode 1 0 == Mode 0
* 6 - PB6 output - Reset 1 == Reset all but MPU 0 == No reset
* and MIC PIA
* 7 - PB7 output - not used
*/
m_mic_pia->writepa_handler().set([this](offs_t offset, uint8_t data)
{
LOGMIC("->MIC PIA: Port A write %02x\n", data);
LOGKBD(" PA1 - KBD reset %s\n", BIT(data, 1) ? "active" : "inactive");
m_kbd->rst_line_w(BIT(data, 1) ? ASSERT_LINE : CLEAR_LINE);
LOGMIC(" PA5 - Int out %s\n", BIT(data, 5) ? "enabled": "disabled");
LOGMIC(" PA6 - I4 latch %s\n", BIT(data, 6) ? "enabled": "disabled");
});
PIA6821(config, m_diapia, 0); // Display PIA, controls how the CRTC accesses memory etc
m_diapia->readcb1_handler().set([this](offs_t offset) -> uint8_t { LOGDIA("DIA PIA: CB1_r\n"); return 0;});
m_diapia->cb2_handler().set([this](offs_t offset, uint8_t data) { LOGDIA("DIA PIA: CB2_w\n"); });
m_diapia->writepa_handler().set([this](offs_t offset, uint8_t data) { LOGDIA("DIA PIA: PA_w\n"); });
m_diapia->writepb_handler().set([this](offs_t offset, uint8_t data) { LOGDIA("DIA PIA: PB_w\n"); });
m_diapia->readpa_handler().set([this](offs_t offset) -> uint8_t { LOGDIA("DIA PIA: PA_r\n"); return 0;});
m_diapia->readpb_handler().set([this](offs_t offset) -> uint8_t { LOGDIA("DIA PIA: PB_r\n"); return 0;});
m_diapia->readca1_handler().set([this](offs_t offset) -> uint8_t { LOGDIA("DIA PIA: CA1_r\n"); return 0;});
m_diapia->readca2_handler().set([this](offs_t offset) -> uint8_t { LOGDIA("DIA PIA: CA2_r\n"); return 0;});
m_mic_pia->writepb_handler().set([this](offs_t offset, uint8_t data)
{
LOGMIC("->MIC PIA: Port B write %02x\n", data);
LOGMIC(" PB0 - Reset PC-error %s\n", BIT(data, 0) ? "active" : "inactive");
LOGMIC(" PB1 - %s generated by MPU\n", BIT(data, 1) ? "VMAX" : "VMA 1");
LOGMIC(" PB2 - %s generated by DMA\n", BIT(data, 2) ? "VMAX" : "VMA 1");
LOGMIC(" PB3 - %sKB Display Memory\n", BIT(data, 3) ? "4" : "8");
LOGMIC(" PB4 - Option Char Generator %s\n", BIT(data, 4) ? "enabled" : "disabled");
LOGMIC(" PB5 - MPU Address Mode %s\n", BIT(data, 5) ? "1" : "0");
LOGMIC(" PB6 - Reset of devices %s\n", BIT(data, 6) ? "active" : "inactive");
});
m_mic_pia->readpa_handler().set([this](offs_t offset) -> uint8_t
{
uint8_t data = (1U << 2); // MCU is not in test mode
LOGMIC("<-MIC PIA: Port A read\n");
LOGMIC(" PA2 - MCU test mode %s\n", BIT(data, 2) ? "inactive" : "active");
return 0;
});
m_mic_pia->readpb_handler().set([this](offs_t offset) -> uint8_t { LOGMIC("<-MIC PIA: Port B read\n"); return 0;});
m_mic_pia->readca1_handler().set([this](offs_t offset) -> uint8_t { LOGMIC("<-MIC PIA: CA1 read\n"); return 0;});
m_mic_pia->readca2_handler().set([this](offs_t offset) -> uint8_t { LOGMIC("<-MIC PIA: CA2 read\n"); return 0;});
PIA6821(config, m_dia_pia, 0); // Display PIA, controls how the CRTC accesses memory etc
m_dia_pia->readcb1_handler().set([this](offs_t offset) -> uint8_t { LOGDIA("DIA PIA: CB1_r\n"); return 0;});
m_dia_pia->cb2_handler().set([this](offs_t offset, uint8_t data) { LOGDIA("DIA PIA: CB2_w %d\n", data); });
m_dia_pia->writepa_handler().set([this](offs_t offset, uint8_t data) { LOGDIA("DIA PIA: PA_w %02x\n", data); });
m_dia_pia->writepb_handler().set([this](offs_t offset, uint8_t data) { LOGDIA("DIA PIA: PB_w %02x\n", data); });
m_dia_pia->readpa_handler().set([this](offs_t offset) -> uint8_t { LOGDIA("DIA PIA: PA_r\n"); return 0;});
m_dia_pia->readpb_handler().set([this](offs_t offset) -> uint8_t { LOGDIA("DIA PIA: PB_r\n"); return 0;});
m_dia_pia->readca1_handler().set([this](offs_t offset) -> uint8_t { LOGDIA("DIA PIA: CA1_r\n"); return 0;});
m_dia_pia->readca2_handler().set([this](offs_t offset) -> uint8_t { LOGDIA("DIA PIA: CA2_r\n"); return 0;});
/* The ACIA RxC and TxC are fed from the systemclock divided through a by 14 dividing 74163, from the tech manual:
"A clock of 76 kHz is provided for the ACIA by the timing logic. ACIA divides this clock by 64 (Bit transfer rate 1188 Hz) and
synchronizes internally to received data. Furthermore ACIA may provide interrupt (at level 3) when transmit register is empty,
receive register is full or an error has occured. */
ACIA6850(config, m_kbd_acia, XTAL(19'170'000) / 18);
CLOCK(config, "acia_clock", (XTAL(19'170'000) / 18) / 14 ).signal_handler().set([this](int state) { m_kbd_acia->write_txc(state); m_kbd_acia->write_rxc(state); });
m_kbd_acia->irq_handler().set("irq3", FUNC(input_merger_device::in_w<3>));
m_kbd_acia->txd_handler().set([this](bool state)
{
if (m_txd != state)
{
LOGBITS("4110->KBD: %d\n", state);
m_txd = state;
m_kbd->rxd_w(m_txd);
}
});
MC6854(config, m_tia_adlc, XTAL(19'170'000) / 18);
m_tia_adlc->out_irq_cb().set("irq7", FUNC(input_merger_device::in_w<7>));
m_tia_adlc->out_rdsr_cb().set([this](bool state){ LOGDMA("TIA ADLC RDSR: %d\n", state); m_tia_dma->dreq_w<1>(state); });
m_tia_adlc->out_tdsr_cb().set([this](bool state){ LOGDMA("TIA ADLC TDSR: %d\n", state); m_tia_dma->dreq_w<0>(state); });
MC6844(config, m_tia_dma, XTAL(19'170'000) / 18);
//m_tia_dma->out_int_callback().set([this](bool state){ LOGDMA("TIA DMA IRQ: %d\n", state); }); // Used as DEND (end of dma) towards the ADLC through some logic
m_tia_dma->out_drq1_callback().set([this](bool state){ LOGDMA("TIA DMA DRQ1: %d\n", state); m_tia_dma->dgrnt_w(state); });
//m_tia_dma->out_drq2_callback().set([this](bool state){ LOGDMA("TIA DMA DRQ2: %d\n", state); }); // Not connected
m_tia_dma->in_ior_callback<1>().set([this](offs_t offset) -> uint8_t { return m_tia_adlc->dma_r(); });
m_tia_dma->out_memw_callback().set([this](offs_t offset, uint8_t data) { m_maincpu->space(AS_PROGRAM).write_byte(offset, data); });
/* 74LS273 latch inputs of interruptt sources */
INPUT_MERGER_ANY_HIGH(config, "irq0").output_handler().set(FUNC(alfaskop4110_state::irq_w<0>));
INPUT_MERGER_ANY_HIGH(config, "irq1").output_handler().set(FUNC(alfaskop4110_state::irq_w<1>));
INPUT_MERGER_ANY_HIGH(config, "irq2").output_handler().set(FUNC(alfaskop4110_state::irq_w<2>));
INPUT_MERGER_ANY_HIGH(config, "irq3").output_handler().set(FUNC(alfaskop4110_state::irq_w<3>));
INPUT_MERGER_ANY_HIGH(config, "irq4").output_handler().set(FUNC(alfaskop4110_state::irq_w<4>));
INPUT_MERGER_ANY_HIGH(config, "irq5").output_handler().set(FUNC(alfaskop4110_state::irq_w<5>));
INPUT_MERGER_ANY_HIGH(config, "irq6").output_handler().set(FUNC(alfaskop4110_state::irq_w<6>));
INPUT_MERGER_ANY_HIGH(config, "irq7").output_handler().set(FUNC(alfaskop4110_state::irq_w<7>));
}
void alfaskop4110_state::machine_start()
{
save_item(NAME(m_irq));
save_item(NAME(m_imsk));
timer_set(attotime::from_msec(5000), TIMER_POLL_START);
// Hard wired inputs
m_kbd_acia->write_cts(0);
m_kbd_acia->write_dcd(0);
}
void alfaskop4110_state::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
{
// Debug feature, inserts a poll SDLC frame through the ADLC, it ends up at address 0x140 in RAM through DMA
switch (id)
{
case TIMER_POLL_START:
/* The serial transfer of 8 bits is complete. Now trigger INT7. */
LOGADLC("Starting poll message\n");
m_tia_adlc->set_rx(0);
timer_set(attotime::from_hz(300000), TIMER_POLL_BIT);
break;
case TIMER_POLL_BIT:
if (flank)
{
if (index != 0 && index != 7 && BIT(txBuf[index], (pos % 8)) && ones == 5)
{
LOGADLC("%d%c", 2, (pos % 8) == 7 ? '\n' : ' ');
m_tia_adlc->set_rx(0);
ones = 0;
}
else
{
LOGADLC("%d%c", BIT(txBuf[index], (pos % 8)), (pos % 8) == 7 ? '\n' : ' ');
m_tia_adlc->set_rx(BIT(txBuf[index], (pos % 8)));
if (index != 0 && index != 7 && BIT(txBuf[index], (pos % 8)))
ones++;
else
ones = 0;
pos++;
index = pos / 8;
}
}
m_tia_adlc->rxc_w(flank ? 1 : 0);
if (index < 8)
timer_set(attotime::from_hz(300000) / 2, TIMER_POLL_BIT);
flank = !flank;
break;
}
}
void alfaskop4110_state::machine_reset()
{
m_irq = 0x00;
m_kbd->rst_line_w(ASSERT_LINE);
// Hard wired inputs
m_kbd_acia->write_cts(0);
m_kbd_acia->write_dcd(0);
ACIA6850(config, m_kbdacia, 0);
//CLOCK(config, "acia_clock", ACIA_CLOCK).signal_handler().set(FUNC(alfaskop4110_state::write_acia_clock));
}
void alfaskop4120_state::alfaskop4120(machine_config &config)
@ -597,7 +237,7 @@ void alfaskop4120_state::alfaskop4120(machine_config &config)
M6800(config, m_maincpu, XTAL(19'170'000) / 18); // Verified from service manual
m_maincpu->set_addrmap(AS_PROGRAM, &alfaskop4120_state::mem_map);
PIA6821(config, m_mic_pia, 0); // Main Board PIA
PIA6821(config, m_micpia, 0); // Main board PIA
PIA6821(config, m_fdapia, 0); // Floppy Disk PIA
}
@ -607,7 +247,7 @@ void alfaskop4101_state::alfaskop4101(machine_config &config)
M6800(config, m_maincpu, XTAL(19'170'000) / 18); // Verified from service manual
m_maincpu->set_addrmap(AS_PROGRAM, &alfaskop4101_state::mem_map);
PIA6821(config, m_mic_pia, 0); // Main board PIA
PIA6821(config, m_micpia, 0); // Main board PIA
}
/* ROM definitions */
@ -617,9 +257,6 @@ ROM_START( alfaskop4110 ) // Display Unit
ROM_REGION( 0x800, "chargen", ROMREGION_ERASEFF )
ROM_LOAD( "e3405972067500.bin", 0x0000, 0x0400, CRC(fb12b549) SHA1(53783f62c5e51320a53e053fbcf8b3701d8a805f))
ROM_LOAD( "e3405972067600.bin", 0x0400, 0x0400, CRC(c7069d65) SHA1(587efcbee036d4c0c5b936cc5d7b1f97b6fe6dba))
ROM_REGION( 0xff, PLA1_TAG, 0 )
//ROM_LOAD( "dtc_a_e34062_0100_ic50_e3405970303601_ml.bin", 0x00, 0xf5, CRC(b37395f2) SHA1(a00dc77d4bef084c0ddceef618986d83c69b1d65) ) // Signetics_N82S100N.bin MAXLOADER format
ROM_LOAD( "dtc_a_e34062_0100_ic50_e3405970303601.bin", 0x00, 0xfa, CRC(16339b7a) SHA1(9b313a7526460dc9bcedfda25bece91c924f0ddc) ) // Signetics_N82S100N.bin DATAIO format
ROM_END
ROM_START( alfaskop4120 ) // Flexible Disk Unit
@ -634,7 +271,7 @@ ROM_END
/* Driver(S) */
// Only 4101 should exist as a driver in the end, making the 4110 and 4120 as slots devices on the SS3 bus, time will tell
// Only 4101 may exist as a driver in the end making the 4110 and 4120 as slots devices on the SS3 bus, time will tell
// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS
COMP( 1984, alfaskop4110, 0, 0, alfaskop4110, alfaskop4110, alfaskop4110_state, empty_init, "Ericsson", "Alfaskop Display Unit 4110", MACHINE_IS_SKELETON)

View File

@ -1,397 +0,0 @@
// license:BSD-3-Clause
// copyright-holders: Joakim Larsson Edström
/**********************************************************************
Alfaskop 4110 keyboard, emulation of the KeyBoard Unit KBU 4140. which often
was attached to the numerical Keyboard eXpansion Unit KXE 4141 which is not
emulated yet. There is also an optional Magnetic Identification Device MID 4131
TTL-level bi-directional serial matrix keyboard
The KBU 4140 keyboard is controlled by a MC6802@3'579'000Hz in combo with a MC6846.
The key matrix is scanned with the help of two 74LS164 which is also extended to the
KXE 4141. The columns are read through a 74LS240. There are 8 LEDs which are
latched by a 74LS374. The I/O port on the MC6846 is connected to a magnet strip
reader through a MIA interface
The keyboard serial interface line is interpreted and generated by the timer in
the MC6846 where both TX and Rx shares the same line on the keyboard side. The
keyboard remains silent until spoken to by the host computer to avoid collisions.
Credits
-------
The MC6846 ROM and address decoder ROM were dumped by Dalby Datormuseum whom
also provided documentation and schematics of the keyboard
https://sites.google.com/site/dalbydatormuseum/home
**********************************************************************/
#include "emu.h"
#include "alfaskop_s41_kb.h"
#include "cpu/m6800/m6800.h"
//**************************************************************************
// CONFIGURABLE LOGGING
//**************************************************************************
#define LOG_IRQ (1U << 1)
#define LOG_RESET (1U << 2)
#define LOG_BITS (1U << 3)
#define LOG_UI (1U << 4)
#define LOG_LEDS (1U << 5)
#define LOG_ROM (1U << 6)
#define LOG_ADEC (1U << 7)
#define LOG_IO (1U << 8)
//#define VERBOSE (LOG_GENERAL|LOG_IO|LOG_IRQ|LOG_LEDS|LOG_BITS|LOG_RESET)
//#define LOG_OUTPUT_STREAM std::cout
#include "logmacro.h"
#define LOGIRQ(...) LOGMASKED(LOG_IRQ, __VA_ARGS__)
#define LOGRST(...) LOGMASKED(LOG_RESET, __VA_ARGS__)
#define LOGBITS(...) LOGMASKED(LOG_BITS, __VA_ARGS__)
#define LOGUI(...) LOGMASKED(LOG_UI, __VA_ARGS__)
#define LOGLEDS(...) if (!machine().side_effects_disabled()) LOGMASKED(LOG_LEDS, __VA_ARGS__)
#define LOGROM(...) if (!machine().side_effects_disabled()) LOGMASKED(LOG_ROM, __VA_ARGS__)
#define LOGADEC(...) if (!machine().side_effects_disabled()) LOGMASKED(LOG_ADEC, __VA_ARGS__)
#define LOGIO(...) if (!machine().side_effects_disabled()) LOGMASKED(LOG_IO, __VA_ARGS__)
//**************************************************************************
// MACROS / CONSTANTS
//**************************************************************************
#define M6800_TAG "mcu"
namespace {
INPUT_PORTS_START(alfaskop_s41_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)) // 77
PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("KP +") PORT_CODE(KEYCODE_PLUS_PAD) PORT_CHAR('+') // 78
PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("KP 5") PORT_CODE(KEYCODE_5_PAD) PORT_CHAR('5') // 76
PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("* PRINT") PORT_CODE(KEYCODE_TILDE) PORT_CHAR('*') PORT_CHAR(UCHAR_MAMEKEY(PRTSCR)) // 55
PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("R Shift") PORT_CODE(KEYCODE_RSHIFT) PORT_CHAR(UCHAR_SHIFT_1) // 54
PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-') PORT_CHAR('_') // 53
PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(". :") PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR(':') // 52
PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("F5") PORT_CODE(KEYCODE_F5) PORT_CHAR(UCHAR_MAMEKEY(F5)) // 63
PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("F6") PORT_CODE(KEYCODE_F6) PORT_CHAR(UCHAR_MAMEKEY(F6)) // 64
PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_UNUSED ) // no scancode is sent
PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("CTRL") PORT_CODE(KEYCODE_LCONTROL) PORT_CHAR(UCHAR_MAMEKEY(LCONTROL)) // 29
PORT_BIT( 0x0800, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(", ;") PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR(';') // 51
PORT_BIT( 0x1000, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_D) PORT_CHAR('D') PORT_CHAR('d') // 32
PORT_BIT( 0x2000, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_X) PORT_CHAR('X') PORT_CHAR('x') // 45
PORT_BIT( 0x4000, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_C) PORT_CHAR('C') PORT_CHAR('c') // 46
PORT_BIT( 0x8000, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_J) PORT_CHAR('J') PORT_CHAR('j') // 36
PORT_START("P14")
PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_UNUSED ) // 00 - keyboard error
PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("BREAK") PORT_CODE(KEYCODE_PAUSE) PORT_CHAR(UCHAR_MAMEKEY(PAUSE)) // 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)) // 71
PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_UNUSED ) // ff - keyboard error
PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_TILDE) PORT_CHAR('^') PORT_CHAR('~') PORT_CHAR(']') // 27
PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR(0x00e5) PORT_CHAR(0x00c5) PORT_CHAR('[') // 26 å Å
PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_P) PORT_CHAR('P') PORT_CHAR('p') // 25
PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("F1") PORT_CODE(KEYCODE_F1) PORT_CHAR(UCHAR_MAMEKEY(F1)) // 59
PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("F2") PORT_CODE(KEYCODE_F2) PORT_CHAR(UCHAR_MAMEKEY(F2)) // 60
PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_W) PORT_CHAR('w') PORT_CHAR('W') // 17
PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_E) PORT_CHAR('e') PORT_CHAR('E') // 18
PORT_BIT( 0x0800, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O') // 24
PORT_BIT( 0x1000, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_R) PORT_CHAR('r') PORT_CHAR('R') // 19
PORT_BIT( 0x2000, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_T) PORT_CHAR('t') PORT_CHAR('T') // 20
PORT_BIT( 0x4000, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_Y) PORT_CHAR('y') PORT_CHAR('Y') // 21
PORT_BIT( 0x8000, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_I) PORT_CHAR('i') PORT_CHAR('I') // 23
PORT_START("P13")
PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_NUMLOCK) PORT_CHAR(UCHAR_MAMEKEY(NUMLOCK)) // 69
PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_UNUSED ) // 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)) // 14
PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('=') PORT_CHAR('+') // 13
PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-') PORT_CHAR('_') // 12
PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR(')') // 11
PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR('(') // 10
PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!') // 02
PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("ESC") PORT_CODE(KEYCODE_ESC) PORT_CHAR(UCHAR_MAMEKEY(ESC)) // 01
PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('@') // 03
PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('#') // 04
PORT_BIT( 0x0800, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('*') // 09
PORT_BIT( 0x1000, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$') // 05
PORT_BIT( 0x2000, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%') // 06
PORT_BIT( 0x4000, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('^') // 07
PORT_BIT( 0x8000, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('&') // 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)) // 73
PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("KP -") PORT_CODE(KEYCODE_MINUS_PAD) PORT_CHAR(UCHAR_MAMEKEY(MINUS_PAD)) // 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)) // 72
PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_TILDE) PORT_CHAR('`') PORT_CHAR('~') // 41
PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR('\'') PORT_CHAR('"') // 40
PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_COLON) PORT_CHAR(';') PORT_CHAR(':') // 39
PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_L) PORT_CHAR('l') PORT_CHAR('L') // 38
PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("F3") PORT_CODE(KEYCODE_F3) PORT_CHAR(UCHAR_MAMEKEY(F3)) // 61
PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("F4") PORT_CODE(KEYCODE_F4) PORT_CHAR(UCHAR_MAMEKEY(F4)) // 62
PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q') // 16
PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("TAB") PORT_CODE(KEYCODE_TAB) PORT_CHAR(9) // 15
PORT_BIT( 0x0800, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_K) PORT_CHAR('k') PORT_CHAR('K') // 37
PORT_BIT( 0x1000, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F) PORT_CHAR('f') PORT_CHAR('F') // 33
PORT_BIT( 0x2000, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_G) PORT_CHAR('g') PORT_CHAR('G') // 34
PORT_BIT( 0x4000, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_H) PORT_CHAR('h') PORT_CHAR('H') // 35
PORT_BIT( 0x8000, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_U) PORT_CHAR('u') PORT_CHAR('U') // 22
PORT_START("P11")
PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_DEL_PAD) PORT_CHAR(UCHAR_MAMEKEY(COMMA_PAD)) // 83
PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("RETURN") PORT_CODE(KEYCODE_ENTER) PORT_CHAR(13) // 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)) // 82
PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_UNUSED ) // 89 - no key
PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_UNUSED ) // 86 - no key
PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_UNUSED ) // 87 - no key
PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_UNUSED ) // 88 - no key
PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("F9") PORT_CODE(KEYCODE_F9) PORT_CHAR(UCHAR_MAMEKEY(F9)) // 67
PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("F10") PORT_CODE(KEYCODE_F10) PORT_CHAR(UCHAR_MAMEKEY(F10)) // 68
PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_UNUSED ) // scan code ff - keyboard error
PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR('\\') // 43
PORT_BIT( 0x0800, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("CAPS LOCK") PORT_CODE(KEYCODE_CAPSLOCK) PORT_CHAR(UCHAR_MAMEKEY(CAPSLOCK)) // 58
PORT_BIT( 0x1000, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("SHIFT LOCK") PORT_CODE(KEYCODE_LALT) // 56
PORT_BIT( 0x2000, IP_ACTIVE_LOW, IPT_UNUSED ) // 85 - no key
PORT_BIT( 0x4000, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V') // 47
PORT_BIT( 0x8000, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ') // 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) // 81
PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_UNUSED ) // 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)) // 80
PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("NEW LINE") PORT_CODE(KEYCODE_ENTER_PAD) PORT_CHAR(UCHAR_MAMEKEY(ENTER_PAD)) // 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)) // 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)) // 75
PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_UNUSED ) // ff - keyboard error
PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("F7") PORT_CODE(KEYCODE_F7) PORT_CHAR(UCHAR_MAMEKEY(F7)) // 65
PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("F8") PORT_CODE(KEYCODE_F8) PORT_CHAR(UCHAR_MAMEKEY(F8)) // 66
PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_LSHIFT) PORT_CHAR(UCHAR_SHIFT_1) // 42
PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_Z) PORT_CHAR('z') PORT_CHAR('Z') // 44
PORT_BIT( 0x0800, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_M) PORT_CHAR('m') PORT_CHAR('M') // 50
PORT_BIT( 0x1000, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_A) PORT_CHAR('a') PORT_CHAR('A') // 30
PORT_BIT( 0x2000, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_S) PORT_CHAR('s') PORT_CHAR('S') // 31
PORT_BIT( 0x4000, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_B) PORT_CHAR('b') PORT_CHAR('B') // 48
PORT_BIT( 0x8000, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_N) PORT_CHAR('n') PORT_CHAR('N') // 49
INPUT_PORTS_END
//-------------------------------------------------
// ROM( alfaskop_s41_kb )
//-------------------------------------------------
ROM_START( alfaskop_s41_kb )
ROM_REGION( 0x800, M6800_TAG, 0 )
ROM_LOAD( "kbc_e34066_0000_ic3.bin", 0x000, 0x800, CRC(a1232241) SHA1(45d1b038bfbd04e1b7e3718a27202280c5257989) )
ROM_REGION( 0x20, "ad_rom", 0 ) // Address decoder
ROM_LOAD( "kbc_e34066_0000_ic4_e3405970280400.bin", 0x00, 0x20, CRC(f26acca3) SHA1(ac8c607d50bb588c1da4ad1602665c785ebd29b3) )
ROM_END
} // anonymous namespace
//**************************************************************************
// DEVICE DEFINITIONS
//**************************************************************************
DEFINE_DEVICE_TYPE(ALFASKOP_S41_KB, alfaskop_s41_keyboard_device, "alfaskop_s41_kb", "Alfaskop 4110 keyboard")
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
//-------------------------------------------------
// alfaskop_s41_keyboard_device - constructor
//-------------------------------------------------
alfaskop_s41_keyboard_device::alfaskop_s41_keyboard_device(
machine_config const &mconfig,
char const *tag,
device_t *owner,
uint32_t clock)
: device_t(mconfig, ALFASKOP_S41_KB, tag, owner, clock)
, m_mcu(*this, M6800_TAG)
, m_mc6846(*this, "mc6846")
, m_rows(*this, "P1%u", 0)
, m_txd_cb(*this)
, m_leds_cb(*this)
, m_rxd_high(true)
, m_txd_high(true)
, m_hold(true)
, m_col_select(0)
, m_p1(0)
, m_leds(0)
{
}
WRITE_LINE_MEMBER(alfaskop_s41_keyboard_device::rxd_w)
{
LOGBITS("KBD bit presented: %d\n", state);
//m_rxd_high = CLEAR_LINE != state;
}
// WRITE_LINE_MEMBER(alfaskop_s41_keyboard_device::hold_w)
// {
// m_hold = CLEAR_LINE == state;
// }
WRITE_LINE_MEMBER(alfaskop_s41_keyboard_device::rst_line_w)
{
if (state == CLEAR_LINE)
{
m_mcu->set_input_line(INPUT_LINE_RESET, CLEAR_LINE);
LOGRST("KBD: Keyboard mcu reset line is cleared\n");
}
else
{
m_mcu->set_input_line(INPUT_LINE_RESET, ASSERT_LINE);
LOGRST("KBD: Keyboard mcu reset line is asserted\n");
}
}
//-------------------------------------------------
// device_start - device specific startup
//-------------------------------------------------
void alfaskop_s41_keyboard_device::device_start()
{
m_txd_cb.resolve_safe();
m_leds_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 alfaskop_s41_keyboard_device::device_add_mconfig(machine_config &config)
{
M6802(config, m_mcu, XTAL(3'579'545)); // Crystal verified from schematics
m_mcu->set_addrmap(AS_PROGRAM, &alfaskop_s41_keyboard_device::alfaskop_s41_kb_mem);
MC6846(config, m_mc6846, XTAL(3'579'545) / 4); // Driven by E from 6802 == XTAL / 4
m_mc6846->irq().set([this](bool state)
{
LOGIRQ(" [timer IRQ: %s] ", state == ASSERT_LINE ? "asserted" : "cleared");
m_mcu->set_input_line(M6802_IRQ_LINE, state);
});
m_mc6846->cp2().set([this](bool state){ LOG("CP2:%d\n", state); });
// MIA ID interrupt: m_mc6846->set_input_cp1(1);
m_mc6846->cto().set([this](bool state){ LOG("CTO:%d\n", state); }); // Not connected to anything
}
//-------------------------------------------------
// input_ports - device-specific input ports
//-------------------------------------------------
ioport_constructor alfaskop_s41_keyboard_device::device_input_ports() const
{
return INPUT_PORTS_NAME( alfaskop_s41_kb );
}
//-------------------------------------------------
// ADDRESS_MAP( alfaskop_s41_kb_mem )
//-------------------------------------------------
void alfaskop_s41_keyboard_device::alfaskop_s41_kb_mem(address_map &map)
{
map(0x0000, 0x007f).ram(); // Internal RAM
/* A 32 byte decoder ROM connects A0-A4 to A11, A12, A13, A15 and to an external port pin, A14 is not decoded!
* c3 c3 c3 c3 c3 c3 c3 c3 c3 c3 c3 c3 c3 c3 c3 c3 - if external port pin is low
* c3 c3 c3 c3 c5 c6 cb c3 d3 c3 c3 c3 c3 c3 43 f3 - if external port pin is high - normal operation
*
* Decoder rom byte bits as follows
* 0 - 0x01 Start scanning
* 1 - 0x02 read col
* 2 - 0x04 shift col clock
* 3 - 0x08 set lamp data
* 4 - 0x10 CS1 mc6846 I/O access - active low
* 5 - 0x20 CS0 mc6846 ROM access - active high
* 6 - 0x40 n/c?
* 7 - 0x80 to KBX
*
* F3 <- 0x0f <- 1-11 1 == b800-bfff, f800-ffff // 1111 0011 MC6846 Internal ROM access (CS0 - active high)
* 43 <- 0x0e <- 1-11 0 == b000-b7ff, f000-f7ff // 0100 0011
* c3 <- 0x0d <- 1-10 1 == a800-afff, e800-efff // 1100 0011
* c3 <- 0x0c <- 1-10 0 == a000-a7ff, e000-e7ff // 1100 0011
* c3 <- 0x0b <- 1-01 1 == 9800-9fff, d800-dfff // 1100 0011
* c3 <- 0x0a <- 1-01 0 == 9000-97ff, d000-d7ff // 1100 0011
* c3 <- 0x09 <- 1-00 1 == 8800-8fff, c800-cfff // 1100 0011
* d3 <- 0x08 <- 1-00 0 == 8000-87ff, c000-c7ff // 1101 0011 MC6846 Internal I/O access (CS1 - active high)
* c3 <- 0x07 <- 0-11 1 == 3800-3fff, 7800-7fff // 1100 0011
* cb <- 0x06 <- 0-11 0 == 3000-37ff, 7000-77ff // 1100 1011 Set lamp data
* c6 <- 0x05 <- 0-10 1 == 2800-2fff, 6800-6fff // 1100 0110 start scan
* c5 <- 0x04 <- 0-10 0 == 2000-27ff, 6000-67ff // 1100 0101 read col
* c3 <- 0x03 <- 0-01 1 == 1800-1fff, 5800-5fff // 1100 0011
* c3 <- 0x02 <- 0-01 0 == 1000-17ff, 5000-57ff // 1100 0011
* c3 <- 0x01 <- 0-00 1 == 0800-0fff, 4800-4fff // 1100 0011
* c3 <- 0x00 <- 0-00 0 == 0000-07ff, 4000-47ff // 1100 0011
*/
map(0x0080, 0xffff).lrw8(NAME([this](address_space &space, offs_t offset) -> uint8_t
{
uint16_t addr = offset + 0x80;
uint8_t index = 0x10 | ((((addr & 0x8000) | ((addr & 0x3800) << 1)) >> 12) & 0x000f); // 0x10 | (((A15 | A13 | A12 | A11) >> 12)
uint8_t ret = 0;
LOGADEC("address_r %04x -> index %02x: %02x\n", offset + 0x80, index, memregion("ad_rom")->base ()[index]);
switch (memregion("ad_rom")->base ()[index])
{
case 0xf3:
ret = memregion(M6800_TAG)->base ()[addr & 0x07ff];
LOGROM(" - ROM %04x: %02x\n", addr & 0x7ff, ret);
break;
case 0xd3:
LOGIO(" - I/O read mc6846 %04x", addr & 0x07);
ret = m_mc6846->read(space, (offs_t)(addr & 0x07));
LOGIO(": %02x\n", ret);
break;
case 0xc3:
break; // Idle
default:
logerror(" - unmapped read access at %04x through %02x\n", addr, memregion("ad_rom")->base ()[index]);
}
return ret;
}),
NAME( [this](address_space &space, offs_t offset, uint8_t data)
{
uint16_t addr = offset + 0x80;
uint8_t index = 0x10 | ((((addr & 0x8000) | ((addr & 0x3800) << 1)) >> 12) & 0x000f); // 0x10 | (((A15 | A13 | A12 | A11) >> 12)
LOGADEC("address_w %04x -> index %02x: %02x\n", offset + 0x80, index, memregion("ad_rom")->base ()[index]);
switch (memregion("ad_rom")->base ()[index])
{
case 0xd3:
LOGIO(" - I/O write mc6846 %04x, %02x\n", addr & 0x07, data);
m_mc6846->write(space, (offs_t)(addr & 0x07), data);
break;
case 0xcb: // Leds
if (m_leds != data)
{
m_leds_cb(data); m_leds = data;
LOGLEDS(" - I/O write LEDs %04x, %02x\n", addr, data);
}
break;
case 0xc3:
break; // Idle
default:
logerror(" - unmapped write access at %04x, %02x through %02x\n", addr, data, memregion("ad_rom")->base ()[index]);
}
}));
// map(0xf800, 0xffff).rom().region(M6800_TAG,0);
}
//-------------------------------------------------
// rom_region - device-specific ROM region
//-------------------------------------------------
const tiny_rom_entry *alfaskop_s41_keyboard_device::device_rom_region() const
{
return ROM_NAME( alfaskop_s41_kb );
}

View File

@ -1,48 +0,0 @@
// license:BSD-3-Clause
// copyright-holders:Joakim Larsson Edström
#ifndef MAME_MACHINE_ALFASKOP_S41_KB_H
#define MAME_MACHINE_ALFASKOP_S41_KB_H
#pragma once
#include "cpu/m6800/m6800.h"
#include "machine/mc6846.h"
DECLARE_DEVICE_TYPE(ALFASKOP_S41_KB, alfaskop_s41_keyboard_device)
class alfaskop_s41_keyboard_device : public device_t
{
public:
auto txd_cb() { return m_txd_cb.bind(); }
auto leds_cb() { return m_leds_cb.bind(); }
alfaskop_s41_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_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<m6802_cpu_device> m_mcu;
required_device<mc6846_device> m_mc6846;
required_ioport_array<6> m_rows;
devcb_write_line m_txd_cb; // Callback for KBD-> S41
devcb_write8 m_leds_cb; // Callback for all 8 leds -> layout
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;
uint8_t m_p1;
uint8_t m_leds;
void alfaskop_s41_kb_mem(address_map &map);
};
#endif // MAME_MACHINE_ALFASKOP_S41_KB_H

View File

@ -7429,19 +7429,9 @@ static int command_convert(int argc, char *argv[])
/* read the binary data */
err = jedbin_parse(srcbuf, srcbuflen, &jed);
if (err == JEDERR_INVALID_DATA)
switch (err)
{
fprintf(stderr, "Fatal error: Invalid binary JEDEC file\n");
free(srcbuf);
return 1;
}
if (jed.binfmt == DATAIO) // DATAIO is detected and not supported yet, it has swapped inverted/non-inverted line fuses
{
fprintf(stderr, "Fatal error: Unsupported DATAIO PLA format detected\n");
free(srcbuf);
return 1;
case JEDERR_INVALID_DATA: fprintf(stderr, "Fatal error: Invalid binary JEDEC file\n"); free(srcbuf); return 1;
}
/* print out data */