docs: causality audit -- the host-port failure is pre-existing, not caused by the two MAME edits

Four-config A/B (IRQ wiring kept in all four; both mc68681 edits reverted in cfg 4):
the console line and L3FA6E4B0's return are identical (HOST PORT - 15 / 6) in cfg 1-4.
Verdict: PRE-EXISTING.  Neither timing edit causes or relocates the failure.

Methodology correction: hp_ret.lua's labels were on the wrong rets addresses.  The real
returns are L3FA6E4B0 -> 6, L3FA71BC0 -> 0x00900040, L3FA753D0 -> 0x00000408,
L3FA767E0 -> 0.  hp_ret2.lua fixes the addresses.

What 6 is: not a device code.  L3FA6E4B0 reduces five descriptor fields (struct+0x60/
0x80/0xa0/0xc0/0xe0, written from the four sub-test calls) to a 5-bit value; 6 = 0b00110
= "L3FA71BC0 nonzero, L3FA753D0 nonzero".  The caller turns any nonzero into 0x400,
which the dispatcher maps to HOST PORT - 15.  Flagged: L3FA753D0 returns 0x408 while all
its own checks pass, so "nonzero" != "failed its checks"; polarity unresolved.

Leads: COUNTER_READY is set by the firmware's own Start-Counter-Command read (reg 0x0E),
is not in IMR, and is not handled by the ISR -- not the cause.  The DUART clock
(3.6864 MHz) could not be confirmed from the service guide.

Variant MAME files kept in harness/mame/mame_edits/.  Regression holds.
This commit is contained in:
SDD committed 2026-10-16 12:13:39 +03:00
1 parent 031d30da67
commit 72a96862c7
12 files changed
+9183

No files matched your search

+87
View File
@@ -546,3 +546,90 @@ Final state of the acceptance instrument (900 frames):
'LEVEL1/2 ERROR -> HOST PORT - 15 ' <-- unchanged
regression (no VT1200_* env): PC=3FDCE400 samples=199 HOLD
```
---
# CAUSALITY AUDIT (four-config A/B) — the failure is PRE-EXISTING
Reviewed after the owner flagged that "the failure moved backwards" and that my two
MAME edits are both *timing* changes while the newly-blamed sub-test is a *timer* test.
Method: four configurations of the MAME tree (IRQ wiring kept in all four — without it
the test fails even earlier), built with `harness/mame/hp_ab.sh <cfg>`:
| cfg | IRQ | TxRDY edit | overrun edit | console | L3FA6E4B0 return |
|---|---|---|---|---|---|
| 1 | on | on | on | `HOST PORT - 15` | 6 |
| 2 | on | reverted | on | `HOST PORT - 15` | 6 |
| 3 | on | on | reverted | `HOST PORT - 15` | 6 |
| 4 | on | reverted | reverted | `HOST PORT - 15` | 6 |
**Verdict: PRE-EXISTING.** The console line and the caller's return are identical in all
four configurations, including cfg 4 where both MAME edits are reverted to stock. Neither
`mc68681` edit causes or relocates the failure; they only change `RXCHECK`'s own flag
word (Section UPDATE). Variant files are kept in `harness/mame/mame_edits/` (`*.cfg1`,
`*.cfg2`, `*.cfg3`, `*.upstream`).
## Methodology correction (important)
My earlier `hp_ret.lua` attached labels to the **wrong `rets` addresses**, so the return
values I quoted were mis-attributed. Verified against the disassembly, the correct
`rets` sites and their owning functions (prologue register mask) are:
| `rets` | function | return |
|---|---|---|
| `3FA71BB0` | **`L3FA6E4B0`** (the generic port-test routine) | 6 |
| `3FA753C0` | `L3FA71BC0` (baud/timer sub-test) | `0x00900040` |
| `3FA767D0` | `L3FA753D0` (RXCHECK sub-test) | `0x00000408` |
| `3FA77800` | `L3FA767E0` (XMITPASS sub-test) | 0 |
`harness/mame/hp_ret2.lua` uses the corrected addresses. So the owner's premise "6 comes
from `L3FA71BC0`" is off: **`L3FA71BC0` returns `0x00900040`**; the `6` is
`L3FA6E4B0`'s own return.
## What `6` actually is — not a failure code
`L3FA6E4B0` (the routine the level-1 host-port caller invokes) ends its body by reducing
five descriptor fields to a 5-bit value (`3FA718D0`–`3FA71B50`) and returning it:
```
bit0 <- (struct+0x60 != 0) bit3 <- (struct+0xc0 != 0)
bit1 <- (struct+0x80 != 0) bit4 <- (struct+0xe0 != 0)
bit2 <- (struct+0xa0 != 0)
```
with `struct+0x80`/`struct+0xa0`/`struct+0xc0`/`struct+0xe0` set from the four
sub-test calls (`L3FA71BC0`, `L3FA753D0` x2 each). So:
* **`6` = `0b00110`** — a *bitmap of which sub-tests returned nonzero*, not a device
status code: `L3FA71BC0` non-zero and `L3FA753D0` non-zero; `L3FA767E0` returned 0, and
the second-trio fields were never written (the caller aborts after the first trio).
* The host-port caller (`3FA85000`) is `move a8,a8 ; jreq <continue>`: **any** nonzero
value takes the error path, which returns `0x400` (`3FA853A0`). `0x400` is what the
status dispatcher turns into `LEVEL1/2 ERROR -> HOST PORT - 15`.
**Unresolved, and flagged:** the polarity is suspicious. `L3FA753D0` (RXCHECK) returns
`0x408` *while all four of its own checks pass* (flag word 0 — see UPDATE), so "sub-test
returned nonzero" is **not** the same as "sub-test failed its checks". Either its success
path leaves a stale `a8`, or the five fields are pass flags and the caller's test is
inverted relative to my reading. I could not settle this, so `6` should **not** be
treated as a plain failure code until it is.
## The two leads
1. **Counter spuriously active — checked, not the cause.** `ISR` bit `0x08`
(`COUNTER_READY`) is set from frame 1, but MAME sets it in the *Start Counter Command*
read path (`mc68681.cpp` `case 0x0e: start_ct(); set_ISR_bits(INT_COUNTER_READY)`),
and the firmware itself performs that read at boot (`R 0640000E pc=3F200150`). It is
**not** masked into the IRQ (`IMR` = 7 = TxRDYA|RxRDYA|DeltaBreakA, no bit 3), and the
DUART ISR `L3FA78D90` does not handle ISR bit 3, so it cannot disturb the test. `ACR`
reads `0x0000` except when the sub-test writes `0x60`.
2. **DUART clock — unverified.** The service guide has no crystal/baud figure for the
DUART (`grep -i '3.6864|crystal|oscillator' docs/EK-V1000-SV-002_service-guide.txt`
→ nothing; its only "baud" hit is test 16 "Test all baud rates", a level-2+ test).
3.6864 MHz is the 68681 datasheet's nominal and remains the only evidence; **I could
not confirm it** against the guide.
## Acceptance / regression (cfg 1, committed state)
* Console: `LEVEL1/2 TESTING **` then `LEVEL1/2 ERROR -> HOST PORT - 15` — **unchanged**.
* Regression (no `VT1200_*`): `PC=3FDCE400 samples=199` — **holds**.
+25
View File
@@ -0,0 +1,25 @@
#!/bin/sh
# hp_ab.sh <label> -- build the current MAME tree and report the L3FA71BC0
# return value (hp_ret.lua) and the console transcript (cap.lua).
set -e
HERE=$(cd "$(dirname "$0")" && pwd)
M=/home/arti/code/k-space/mame0289/vt1200
LABEL=${1:-cfg}
JOBS=8 "$HERE/build.sh" >/dev/null
cd "$HERE"
echo "== $LABEL =="
export VT1200_VRAM=1 VT1200_BOARD_MODEL=handshake VT1200_BOARD_BUSY_TICKS=2
export VT1200_BOARD_SWITCH="0640000D:70:70" VT1200_DUART=1 VT1200_DUART_SEL=1
rm -f debug.log
timeout 300 "$M" vt1200 -rompath roms -video none -sound none -nothrottle \
-debug -debugger none -debuglog -autoboot_script "$HERE/hp_ret.lua" -autoboot_delay 0 >/dev/null 2>&1 || true
echo "-- returns (hp_ret) --"
grep -v "Breakpoint\|^Currently\|^MAME" debug.log | grep -v '^$' | head -12
rm -f debug.log
CAP_MAX=900 timeout 300 "$M" vt1200 -rompath roms -video none -sound none -nothrottle \
-debug -debugger none -debuglog -autoboot_script "$HERE/cap.lua" -autoboot_delay 0 >/dev/null 2>&1 || true
echo "-- console --"
grep PRINT debug.log | head -6
+15
View File
@@ -0,0 +1,15 @@
local machine = manager.machine
local cpu = machine.devices[':maincpu']
local dbg = machine.debugger
local prog = cpu.spaces['program']
local rd = function(a) return prog:read_u16(a) end
local last={}
local keys={ ISR=0x06400050, IMR=0x06400050, ACR=0x06400040, CUR=0x06400060 }
local n=0
emu.register_frame_done(function()
n=n+1
local isr=rd(0x06400050) & 0xff
if last.isr~=isr then print(string.format("f%4d ISR=%02X ACR=%04X", n, isr, rd(0x06400040))); last.isr=isr end
if n>=520 then machine:exit() end
end,"ctr")
dbg.execution_state='run'
+23
View File
@@ -0,0 +1,23 @@
-- hp_ret2.lua -- return values, with the rets addresses verified from the disassembly:
-- L3FA71BC0 rets @ 3FA753C0, L3FA753D0 (RXCHECK) @ 3FA767D0,
-- L3FA767E0 (XMITPASS) @ 3FA77800.
local machine = manager.machine
local cpu = machine.devices[':maincpu']
local dbg = machine.debugger
if not dbg then print("ERROR: no debugger"); machine:exit(); return end
local function bp(addr, msg)
dbg:command('bpset ' .. addr .. ',,{ printf "' .. msg ..
' a8=%08X a7=%08X a9=%08X a11=%08X a13=%08X\\n", a8, a7, a9, a11, a13 ; g }')
end
bp("3fa753c0", "RET-BC0")
bp("3fa767d0", "RET-RXCHECK")
bp("3fa77800", "RET-XMITPASS")
bp("3fa84fe0", "RET-L3FA6E4B0")
bp("3fa6e4b0", "ENTER-GENERIC")
local n = 0
emu.register_frame_done(function()
n = n + 1
if n >= tonumber(os.getenv("HP_FRAMES") or "700") then print("done "..n); machine:exit() end
end, "vt1200-hp-ret2")
dbg.visible_cpu = cpu
dbg.execution_state = 'run'
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+334
View File
@@ -0,0 +1,334 @@
// license:BSD-3-Clause
// copyright-holders:Mariusz Wojcieszek, R. Belmont
#ifndef MAME_MACHINE_MC68681_H
#define MAME_MACHINE_MC68681_H
#pragma once
#include "diserial.h"
#define MC68681_RX_FIFO_SIZE 3
// forward declaration
class duart_base_device;
// duart_channel class
class duart_channel : public device_t, public device_serial_interface
{
public:
duart_channel(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
// device-level overrides
virtual void device_start() override ATTR_COLD;
virtual void device_reset() override ATTR_COLD;
// device_serial overrides
virtual void rcv_complete() override; // Rx completed receiving byte
virtual void tra_complete() override; // Tx completed sending byte
virtual void tra_callback() override; // Tx send bit
uint8_t read_chan_reg(int reg);
void write_chan_reg(int reg, uint8_t data);
void update_interrupts();
// VT1200 NOTE (local change, not upstream): saw the RxD line so the overrun
// error can be latched on the start bit of the overrunning character (the
// datasheet's timing), rather than at its completion in rx_fifo_push().
void rx_w(int state);
void rx_fifo_push(uint8_t data, uint8_t errors);
uint8_t read_rx_fifo();
void baud_updated();
uint8_t get_chan_CSR();
// Access methods needed for 68340 serial module register model
uint8_t read_MR1(){ return MR1; }
uint8_t read_MR2(){ return MR2; }
void write_MR1(uint8_t data){ MR1 = data; }
void write_MR2(uint8_t data){ MR2 = data; }
void tx_16x_clock_w(bool state);
void rx_16x_clock_w(bool state);
int get_tx_rate() const { return tx_baud_rate; }
private:
/* Registers */
uint8_t CR; /* Command register */
uint8_t CSR; /* Clock select register */
uint8_t MR1; /* Mode register 1 */
uint8_t MR2; /* Mode register 2 */
uint8_t MR_ptr; /* Mode register pointer */
uint8_t SR; /* Status register */
/* State */
int tx_baud_rate, rx_baud_rate;
/* Receiver */
uint8_t rx_enabled;
uint16_t rx_fifo[MC68681_RX_FIFO_SIZE + 1];
int rx_fifo_read_ptr;
int rx_fifo_write_ptr;
int rx_fifo_num;
bool m_rx_line; // VT1200 NOTE (local): previous RxD line state
int m_ch;
/* Transmitter */
uint8_t m_tx_data;
bool m_tx_data_in_buffer;
bool m_tx_break;
uint8_t m_bits_transmitted;
bool m_tx_enabled;
/* Rx/Tx clocking */
uint8_t m_rx_prescaler , m_tx_prescaler;
duart_base_device *m_uart;
void write_MR(uint8_t data);
void write_CR(uint8_t data);
void write_TX(uint8_t data);
void recalc_framing();
};
class duart_base_device : public device_t
{
friend class duart_channel;
public:
required_device<duart_channel> m_chanA;
required_device<duart_channel> m_chanB;
optional_device<duart_channel> m_chanC;
optional_device<duart_channel> m_chanD;
// inline configuration helpers
void set_clocks(int clk3, int clk4, int clk5, int clk6);
void set_clocks(const XTAL &clk3, const XTAL &clk4, const XTAL &clk5, const XTAL &clk6) {
set_clocks(clk3.value(), clk4.value(), clk5.value(), clk6.value());
}
// API
virtual uint8_t read(offs_t offset);
virtual void write(offs_t offset, uint8_t data);
void rx_a_w(int state) { m_chanA->rx_w((uint8_t)state); }
void rx_b_w(int state) { m_chanB->rx_w((uint8_t)state); }
auto irq_cb() { return write_irq.bind(); }
auto a_tx_cb() { return write_a_tx.bind(); }
auto b_tx_cb() { return write_b_tx.bind(); }
auto inport_cb() { return read_inport.bind(); } // deprecated: use ipX_w() instead
auto outport_cb() { return write_outport.bind(); }
// new-style push handlers for input port bits
virtual void ip0_w(int state);
virtual void ip1_w(int state);
virtual void ip2_w(int state);
virtual void ip3_w(int state);
virtual void ip4_w(int state);
virtual void ip5_w(int state);
virtual void ip6_w(int state);
bool irq_pending() const { return (ISR & IMR) != 0; }
protected:
duart_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
// device-level overrides
virtual void device_start() override ATTR_COLD;
virtual void device_reset() override ATTR_COLD;
virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
devcb_write_line write_irq, write_a_tx, write_b_tx, write_c_tx, write_d_tx;
devcb_read8 read_inport;
devcb_write8 write_outport;
int32_t ip3clk, ip4clk, ip5clk, ip6clk;
protected:
virtual void update_interrupts();
private:
TIMER_CALLBACK_MEMBER(duart_timer_callback);
protected:
/* registers */
uint8_t ACR; /* Auxiliary Control Register */
uint8_t IMR; /* Interrupt Mask Register */
uint8_t ISR; /* Interrupt Status Register */
private:
uint8_t OPCR; /* Output Port Conf. Register */
uint8_t OPR; /* Output Port Register */
PAIR CTR; /* Counter/Timer Preset Value */
uint8_t IPCR; /* Input Port Control Register */
/* state */
uint8_t IP_last_state; /* last state of IP bits */
/* timer */
uint8_t half_period;
emu_timer *duart_timer;
bool m_irq_state;
uint32_t get_ct_rate();
uint16_t get_ct_count();
void start_ct(int count);
virtual int calc_baud(int ch, bool rx, uint8_t data);
void clear_ISR_bits(int mask);
void set_ISR_bits(int mask);
int get_ch(duart_channel *ch)
{
if (ch == m_chanA)
{
return 0;
}
else if (ch == m_chanB)
{
return 1;
}
else if (ch == m_chanC)
{
return 2;
}
return 3;
}
duart_channel *get_channel(int chan);
};
class scn2681_device : public duart_base_device
{
public:
scn2681_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
};
class mc68681_device : public duart_base_device
{
public:
mc68681_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
virtual uint8_t read(offs_t offset) override;
virtual void write(offs_t offset, uint8_t data) override;
uint8_t get_irq_vector();
protected:
virtual void device_start() override ATTR_COLD;
virtual void device_reset() override ATTR_COLD;
virtual void update_interrupts() override;
mc68681_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
private:
bool m_read_vector; // if this is read and IRQ is active, it counts as pulling IACK
uint8_t IVR; /* Interrupt Vector Register */
};
/**************************
* ColdFire MCF5206e UART
**************************/
class mcf5206e_uart_device : public duart_base_device
{
public:
mcf5206e_uart_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
virtual uint8_t read(offs_t offset) override;
virtual void write(offs_t offset, uint8_t data) override;
uint8_t get_irq_vector();
// There is no GPIO on the coldfire UART module
void cts_w(int state) { duart_base_device::ip0_w(state); }
virtual void ip1_w(int state) override {}
virtual void ip2_w(int state) override {}
virtual void ip3_w(int state) override {}
virtual void ip4_w(int state) override {}
virtual void ip5_w(int state) override {}
virtual void ip6_w(int state) override {}
protected:
virtual void device_start() override ATTR_COLD;
virtual void device_reset() override ATTR_COLD;
virtual void update_interrupts() override;
virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
mcf5206e_uart_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
private:
virtual int calc_baud(int ch, bool rx, uint8_t data) override;
bool m_read_vector; // if this is read and IRQ is active, it counts as pulling IACK
// ColdFire UART module is essentially two 68681 a-channels with a slighty different register map and no counter
uint8_t IVR; /* Interrupt Vector Register */
uint16_t UBG; /* Baud Rate Generator Prescale Register - Manual erronuosly calls this the timer preload register */
};
class sc28c94_device : public duart_base_device
{
public:
sc28c94_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
auto c_tx_cb() { return write_c_tx.bind(); }
auto d_tx_cb() { return write_d_tx.bind(); }
void rx_c_w(int state) { m_chanC->device_serial_interface::rx_w((uint8_t)state); }
void rx_d_w(int state) { m_chanD->device_serial_interface::rx_w((uint8_t)state); }
virtual uint8_t read(offs_t offset) override;
virtual void write(offs_t offset, uint8_t data) override;
protected:
virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
private:
};
class mc68340_duart_device : public duart_base_device
{
public:
mc68340_duart_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
virtual uint8_t read(offs_t offset) override;
virtual void write(offs_t offset, uint8_t data) override;
protected:
virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
mc68340_duart_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
private:
virtual int calc_baud(int ch, bool rx, uint8_t data) override;
};
class xr68c681_device : public mc68681_device
{
public:
xr68c681_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
virtual uint8_t read(offs_t offset) override;
virtual void write(offs_t offset, uint8_t data) override;
protected:
virtual void device_start() override ATTR_COLD;
virtual void device_reset() override ATTR_COLD;
private:
virtual int calc_baud(int ch, bool rx, uint8_t data) override;
bool m_XTXA,m_XRXA,m_XTXB,m_XRXB; /* X bits for the BRG (selects between 2 BRG tables) */
};
DECLARE_DEVICE_TYPE(SCN2681, scn2681_device)
DECLARE_DEVICE_TYPE(MC68681, mc68681_device)
DECLARE_DEVICE_TYPE(SC28C94, sc28c94_device)
DECLARE_DEVICE_TYPE(MC68340_DUART, mc68340_duart_device)
DECLARE_DEVICE_TYPE(MCF5206E_UART, mcf5206e_uart_device)
DECLARE_DEVICE_TYPE(XR68C681, xr68c681_device)
DECLARE_DEVICE_TYPE(DUART_CHANNEL, duart_channel)
#endif // MAME_MACHINE_MC68681_H
+334
View File
@@ -0,0 +1,334 @@
// license:BSD-3-Clause
// copyright-holders:Mariusz Wojcieszek, R. Belmont
#ifndef MAME_MACHINE_MC68681_H
#define MAME_MACHINE_MC68681_H
#pragma once
#include "diserial.h"
#define MC68681_RX_FIFO_SIZE 3
// forward declaration
class duart_base_device;
// duart_channel class
class duart_channel : public device_t, public device_serial_interface
{
public:
duart_channel(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
// device-level overrides
virtual void device_start() override ATTR_COLD;
virtual void device_reset() override ATTR_COLD;
// device_serial overrides
virtual void rcv_complete() override; // Rx completed receiving byte
virtual void tra_complete() override; // Tx completed sending byte
virtual void tra_callback() override; // Tx send bit
uint8_t read_chan_reg(int reg);
void write_chan_reg(int reg, uint8_t data);
void update_interrupts();
// VT1200 NOTE (local change, not upstream): saw the RxD line so the overrun
// error can be latched on the start bit of the overrunning character (the
// datasheet's timing), rather than at its completion in rx_fifo_push().
void rx_w(int state);
void rx_fifo_push(uint8_t data, uint8_t errors);
uint8_t read_rx_fifo();
void baud_updated();
uint8_t get_chan_CSR();
// Access methods needed for 68340 serial module register model
uint8_t read_MR1(){ return MR1; }
uint8_t read_MR2(){ return MR2; }
void write_MR1(uint8_t data){ MR1 = data; }
void write_MR2(uint8_t data){ MR2 = data; }
void tx_16x_clock_w(bool state);
void rx_16x_clock_w(bool state);
int get_tx_rate() const { return tx_baud_rate; }
private:
/* Registers */
uint8_t CR; /* Command register */
uint8_t CSR; /* Clock select register */
uint8_t MR1; /* Mode register 1 */
uint8_t MR2; /* Mode register 2 */
uint8_t MR_ptr; /* Mode register pointer */
uint8_t SR; /* Status register */
/* State */
int tx_baud_rate, rx_baud_rate;
/* Receiver */
uint8_t rx_enabled;
uint16_t rx_fifo[MC68681_RX_FIFO_SIZE + 1];
int rx_fifo_read_ptr;
int rx_fifo_write_ptr;
int rx_fifo_num;
bool m_rx_line; // VT1200 NOTE (local): previous RxD line state
int m_ch;
/* Transmitter */
uint8_t m_tx_data;
bool m_tx_data_in_buffer;
bool m_tx_break;
uint8_t m_bits_transmitted;
bool m_tx_enabled;
/* Rx/Tx clocking */
uint8_t m_rx_prescaler , m_tx_prescaler;
duart_base_device *m_uart;
void write_MR(uint8_t data);
void write_CR(uint8_t data);
void write_TX(uint8_t data);
void recalc_framing();
};
class duart_base_device : public device_t
{
friend class duart_channel;
public:
required_device<duart_channel> m_chanA;
required_device<duart_channel> m_chanB;
optional_device<duart_channel> m_chanC;
optional_device<duart_channel> m_chanD;
// inline configuration helpers
void set_clocks(int clk3, int clk4, int clk5, int clk6);
void set_clocks(const XTAL &clk3, const XTAL &clk4, const XTAL &clk5, const XTAL &clk6) {
set_clocks(clk3.value(), clk4.value(), clk5.value(), clk6.value());
}
// API
virtual uint8_t read(offs_t offset);
virtual void write(offs_t offset, uint8_t data);
void rx_a_w(int state) { m_chanA->rx_w((uint8_t)state); }
void rx_b_w(int state) { m_chanB->rx_w((uint8_t)state); }
auto irq_cb() { return write_irq.bind(); }
auto a_tx_cb() { return write_a_tx.bind(); }
auto b_tx_cb() { return write_b_tx.bind(); }
auto inport_cb() { return read_inport.bind(); } // deprecated: use ipX_w() instead
auto outport_cb() { return write_outport.bind(); }
// new-style push handlers for input port bits
virtual void ip0_w(int state);
virtual void ip1_w(int state);
virtual void ip2_w(int state);
virtual void ip3_w(int state);
virtual void ip4_w(int state);
virtual void ip5_w(int state);
virtual void ip6_w(int state);
bool irq_pending() const { return (ISR & IMR) != 0; }
protected:
duart_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
// device-level overrides
virtual void device_start() override ATTR_COLD;
virtual void device_reset() override ATTR_COLD;
virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
devcb_write_line write_irq, write_a_tx, write_b_tx, write_c_tx, write_d_tx;
devcb_read8 read_inport;
devcb_write8 write_outport;
int32_t ip3clk, ip4clk, ip5clk, ip6clk;
protected:
virtual void update_interrupts();
private:
TIMER_CALLBACK_MEMBER(duart_timer_callback);
protected:
/* registers */
uint8_t ACR; /* Auxiliary Control Register */
uint8_t IMR; /* Interrupt Mask Register */
uint8_t ISR; /* Interrupt Status Register */
private:
uint8_t OPCR; /* Output Port Conf. Register */
uint8_t OPR; /* Output Port Register */
PAIR CTR; /* Counter/Timer Preset Value */
uint8_t IPCR; /* Input Port Control Register */
/* state */
uint8_t IP_last_state; /* last state of IP bits */
/* timer */
uint8_t half_period;
emu_timer *duart_timer;
bool m_irq_state;
uint32_t get_ct_rate();
uint16_t get_ct_count();
void start_ct(int count);
virtual int calc_baud(int ch, bool rx, uint8_t data);
void clear_ISR_bits(int mask);
void set_ISR_bits(int mask);
int get_ch(duart_channel *ch)
{
if (ch == m_chanA)
{
return 0;
}
else if (ch == m_chanB)
{
return 1;
}
else if (ch == m_chanC)
{
return 2;
}
return 3;
}
duart_channel *get_channel(int chan);
};
class scn2681_device : public duart_base_device
{
public:
scn2681_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
};
class mc68681_device : public duart_base_device
{
public:
mc68681_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
virtual uint8_t read(offs_t offset) override;
virtual void write(offs_t offset, uint8_t data) override;
uint8_t get_irq_vector();
protected:
virtual void device_start() override ATTR_COLD;
virtual void device_reset() override ATTR_COLD;
virtual void update_interrupts() override;
mc68681_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
private:
bool m_read_vector; // if this is read and IRQ is active, it counts as pulling IACK
uint8_t IVR; /* Interrupt Vector Register */
};
/**************************
* ColdFire MCF5206e UART
**************************/
class mcf5206e_uart_device : public duart_base_device
{
public:
mcf5206e_uart_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
virtual uint8_t read(offs_t offset) override;
virtual void write(offs_t offset, uint8_t data) override;
uint8_t get_irq_vector();
// There is no GPIO on the coldfire UART module
void cts_w(int state) { duart_base_device::ip0_w(state); }
virtual void ip1_w(int state) override {}
virtual void ip2_w(int state) override {}
virtual void ip3_w(int state) override {}
virtual void ip4_w(int state) override {}
virtual void ip5_w(int state) override {}
virtual void ip6_w(int state) override {}
protected:
virtual void device_start() override ATTR_COLD;
virtual void device_reset() override ATTR_COLD;
virtual void update_interrupts() override;
virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
mcf5206e_uart_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
private:
virtual int calc_baud(int ch, bool rx, uint8_t data) override;
bool m_read_vector; // if this is read and IRQ is active, it counts as pulling IACK
// ColdFire UART module is essentially two 68681 a-channels with a slighty different register map and no counter
uint8_t IVR; /* Interrupt Vector Register */
uint16_t UBG; /* Baud Rate Generator Prescale Register - Manual erronuosly calls this the timer preload register */
};
class sc28c94_device : public duart_base_device
{
public:
sc28c94_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
auto c_tx_cb() { return write_c_tx.bind(); }
auto d_tx_cb() { return write_d_tx.bind(); }
void rx_c_w(int state) { m_chanC->device_serial_interface::rx_w((uint8_t)state); }
void rx_d_w(int state) { m_chanD->device_serial_interface::rx_w((uint8_t)state); }
virtual uint8_t read(offs_t offset) override;
virtual void write(offs_t offset, uint8_t data) override;
protected:
virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
private:
};
class mc68340_duart_device : public duart_base_device
{
public:
mc68340_duart_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
virtual uint8_t read(offs_t offset) override;
virtual void write(offs_t offset, uint8_t data) override;
protected:
virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
mc68340_duart_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
private:
virtual int calc_baud(int ch, bool rx, uint8_t data) override;
};
class xr68c681_device : public mc68681_device
{
public:
xr68c681_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
virtual uint8_t read(offs_t offset) override;
virtual void write(offs_t offset, uint8_t data) override;
protected:
virtual void device_start() override ATTR_COLD;
virtual void device_reset() override ATTR_COLD;
private:
virtual int calc_baud(int ch, bool rx, uint8_t data) override;
bool m_XTXA,m_XRXA,m_XTXB,m_XRXB; /* X bits for the BRG (selects between 2 BRG tables) */
};
DECLARE_DEVICE_TYPE(SCN2681, scn2681_device)
DECLARE_DEVICE_TYPE(MC68681, mc68681_device)
DECLARE_DEVICE_TYPE(SC28C94, sc28c94_device)
DECLARE_DEVICE_TYPE(MC68340_DUART, mc68340_duart_device)
DECLARE_DEVICE_TYPE(MCF5206E_UART, mcf5206e_uart_device)
DECLARE_DEVICE_TYPE(XR68C681, xr68c681_device)
DECLARE_DEVICE_TYPE(DUART_CHANNEL, duart_channel)
#endif // MAME_MACHINE_MC68681_H
+328
View File
@@ -0,0 +1,328 @@
// license:BSD-3-Clause
// copyright-holders:Mariusz Wojcieszek, R. Belmont
#ifndef MAME_MACHINE_MC68681_H
#define MAME_MACHINE_MC68681_H
#pragma once
#include "diserial.h"
#define MC68681_RX_FIFO_SIZE 3
// forward declaration
class duart_base_device;
// duart_channel class
class duart_channel : public device_t, public device_serial_interface
{
public:
duart_channel(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
// device-level overrides
virtual void device_start() override ATTR_COLD;
virtual void device_reset() override ATTR_COLD;
// device_serial overrides
virtual void rcv_complete() override; // Rx completed receiving byte
virtual void tra_complete() override; // Tx completed sending byte
virtual void tra_callback() override; // Tx send bit
uint8_t read_chan_reg(int reg);
void write_chan_reg(int reg, uint8_t data);
void update_interrupts();
void rx_fifo_push(uint8_t data, uint8_t errors);
uint8_t read_rx_fifo();
void baud_updated();
uint8_t get_chan_CSR();
// Access methods needed for 68340 serial module register model
uint8_t read_MR1(){ return MR1; }
uint8_t read_MR2(){ return MR2; }
void write_MR1(uint8_t data){ MR1 = data; }
void write_MR2(uint8_t data){ MR2 = data; }
void tx_16x_clock_w(bool state);
void rx_16x_clock_w(bool state);
int get_tx_rate() const { return tx_baud_rate; }
private:
/* Registers */
uint8_t CR; /* Command register */
uint8_t CSR; /* Clock select register */
uint8_t MR1; /* Mode register 1 */
uint8_t MR2; /* Mode register 2 */
uint8_t MR_ptr; /* Mode register pointer */
uint8_t SR; /* Status register */
/* State */
int tx_baud_rate, rx_baud_rate;
/* Receiver */
uint8_t rx_enabled;
uint16_t rx_fifo[MC68681_RX_FIFO_SIZE + 1];
int rx_fifo_read_ptr;
int rx_fifo_write_ptr;
int rx_fifo_num;
int m_ch;
/* Transmitter */
uint8_t m_tx_data;
bool m_tx_data_in_buffer;
bool m_tx_break;
uint8_t m_bits_transmitted;
bool m_tx_enabled;
/* Rx/Tx clocking */
uint8_t m_rx_prescaler , m_tx_prescaler;
duart_base_device *m_uart;
void write_MR(uint8_t data);
void write_CR(uint8_t data);
void write_TX(uint8_t data);
void recalc_framing();
};
class duart_base_device : public device_t
{
friend class duart_channel;
public:
required_device<duart_channel> m_chanA;
required_device<duart_channel> m_chanB;
optional_device<duart_channel> m_chanC;
optional_device<duart_channel> m_chanD;
// inline configuration helpers
void set_clocks(int clk3, int clk4, int clk5, int clk6);
void set_clocks(const XTAL &clk3, const XTAL &clk4, const XTAL &clk5, const XTAL &clk6) {
set_clocks(clk3.value(), clk4.value(), clk5.value(), clk6.value());
}
// API
virtual uint8_t read(offs_t offset);
virtual void write(offs_t offset, uint8_t data);
void rx_a_w(int state) { m_chanA->device_serial_interface::rx_w((uint8_t)state); }
void rx_b_w(int state) { m_chanB->device_serial_interface::rx_w((uint8_t)state); }
auto irq_cb() { return write_irq.bind(); }
auto a_tx_cb() { return write_a_tx.bind(); }
auto b_tx_cb() { return write_b_tx.bind(); }
auto inport_cb() { return read_inport.bind(); } // deprecated: use ipX_w() instead
auto outport_cb() { return write_outport.bind(); }
// new-style push handlers for input port bits
virtual void ip0_w(int state);
virtual void ip1_w(int state);
virtual void ip2_w(int state);
virtual void ip3_w(int state);
virtual void ip4_w(int state);
virtual void ip5_w(int state);
virtual void ip6_w(int state);
bool irq_pending() const { return (ISR & IMR) != 0; }
protected:
duart_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
// device-level overrides
virtual void device_start() override ATTR_COLD;
virtual void device_reset() override ATTR_COLD;
virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
devcb_write_line write_irq, write_a_tx, write_b_tx, write_c_tx, write_d_tx;
devcb_read8 read_inport;
devcb_write8 write_outport;
int32_t ip3clk, ip4clk, ip5clk, ip6clk;
protected:
virtual void update_interrupts();
private:
TIMER_CALLBACK_MEMBER(duart_timer_callback);
protected:
/* registers */
uint8_t ACR; /* Auxiliary Control Register */
uint8_t IMR; /* Interrupt Mask Register */
uint8_t ISR; /* Interrupt Status Register */
private:
uint8_t OPCR; /* Output Port Conf. Register */
uint8_t OPR; /* Output Port Register */
PAIR CTR; /* Counter/Timer Preset Value */
uint8_t IPCR; /* Input Port Control Register */
/* state */
uint8_t IP_last_state; /* last state of IP bits */
/* timer */
uint8_t half_period;
emu_timer *duart_timer;
bool m_irq_state;
uint32_t get_ct_rate();
uint16_t get_ct_count();
void start_ct(int count);
virtual int calc_baud(int ch, bool rx, uint8_t data);
void clear_ISR_bits(int mask);
void set_ISR_bits(int mask);
int get_ch(duart_channel *ch)
{
if (ch == m_chanA)
{
return 0;
}
else if (ch == m_chanB)
{
return 1;
}
else if (ch == m_chanC)
{
return 2;
}
return 3;
}
duart_channel *get_channel(int chan);
};
class scn2681_device : public duart_base_device
{
public:
scn2681_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
};
class mc68681_device : public duart_base_device
{
public:
mc68681_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
virtual uint8_t read(offs_t offset) override;
virtual void write(offs_t offset, uint8_t data) override;
uint8_t get_irq_vector();
protected:
virtual void device_start() override ATTR_COLD;
virtual void device_reset() override ATTR_COLD;
virtual void update_interrupts() override;
mc68681_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
private:
bool m_read_vector; // if this is read and IRQ is active, it counts as pulling IACK
uint8_t IVR; /* Interrupt Vector Register */
};
/**************************
* ColdFire MCF5206e UART
**************************/
class mcf5206e_uart_device : public duart_base_device
{
public:
mcf5206e_uart_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
virtual uint8_t read(offs_t offset) override;
virtual void write(offs_t offset, uint8_t data) override;
uint8_t get_irq_vector();
// There is no GPIO on the coldfire UART module
void cts_w(int state) { duart_base_device::ip0_w(state); }
virtual void ip1_w(int state) override {}
virtual void ip2_w(int state) override {}
virtual void ip3_w(int state) override {}
virtual void ip4_w(int state) override {}
virtual void ip5_w(int state) override {}
virtual void ip6_w(int state) override {}
protected:
virtual void device_start() override ATTR_COLD;
virtual void device_reset() override ATTR_COLD;
virtual void update_interrupts() override;
virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
mcf5206e_uart_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
private:
virtual int calc_baud(int ch, bool rx, uint8_t data) override;
bool m_read_vector; // if this is read and IRQ is active, it counts as pulling IACK
// ColdFire UART module is essentially two 68681 a-channels with a slighty different register map and no counter
uint8_t IVR; /* Interrupt Vector Register */
uint16_t UBG; /* Baud Rate Generator Prescale Register - Manual erronuosly calls this the timer preload register */
};
class sc28c94_device : public duart_base_device
{
public:
sc28c94_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
auto c_tx_cb() { return write_c_tx.bind(); }
auto d_tx_cb() { return write_d_tx.bind(); }
void rx_c_w(int state) { m_chanC->device_serial_interface::rx_w((uint8_t)state); }
void rx_d_w(int state) { m_chanD->device_serial_interface::rx_w((uint8_t)state); }
virtual uint8_t read(offs_t offset) override;
virtual void write(offs_t offset, uint8_t data) override;
protected:
virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
private:
};
class mc68340_duart_device : public duart_base_device
{
public:
mc68340_duart_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
virtual uint8_t read(offs_t offset) override;
virtual void write(offs_t offset, uint8_t data) override;
protected:
virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
mc68340_duart_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
private:
virtual int calc_baud(int ch, bool rx, uint8_t data) override;
};
class xr68c681_device : public mc68681_device
{
public:
xr68c681_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
virtual uint8_t read(offs_t offset) override;
virtual void write(offs_t offset, uint8_t data) override;
protected:
virtual void device_start() override ATTR_COLD;
virtual void device_reset() override ATTR_COLD;
private:
virtual int calc_baud(int ch, bool rx, uint8_t data) override;
bool m_XTXA,m_XRXA,m_XTXB,m_XRXB; /* X bits for the BRG (selects between 2 BRG tables) */
};
DECLARE_DEVICE_TYPE(SCN2681, scn2681_device)
DECLARE_DEVICE_TYPE(MC68681, mc68681_device)
DECLARE_DEVICE_TYPE(SC28C94, sc28c94_device)
DECLARE_DEVICE_TYPE(MC68340_DUART, mc68340_duart_device)
DECLARE_DEVICE_TYPE(MCF5206E_UART, mcf5206e_uart_device)
DECLARE_DEVICE_TYPE(XR68C681, xr68c681_device)
DECLARE_DEVICE_TYPE(DUART_CHANNEL, duart_channel)
#endif // MAME_MACHINE_MC68681_H
+328
View File
@@ -0,0 +1,328 @@
// license:BSD-3-Clause
// copyright-holders:Mariusz Wojcieszek, R. Belmont
#ifndef MAME_MACHINE_MC68681_H
#define MAME_MACHINE_MC68681_H
#pragma once
#include "diserial.h"
#define MC68681_RX_FIFO_SIZE 3
// forward declaration
class duart_base_device;
// duart_channel class
class duart_channel : public device_t, public device_serial_interface
{
public:
duart_channel(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
// device-level overrides
virtual void device_start() override ATTR_COLD;
virtual void device_reset() override ATTR_COLD;
// device_serial overrides
virtual void rcv_complete() override; // Rx completed receiving byte
virtual void tra_complete() override; // Tx completed sending byte
virtual void tra_callback() override; // Tx send bit
uint8_t read_chan_reg(int reg);
void write_chan_reg(int reg, uint8_t data);
void update_interrupts();
void rx_fifo_push(uint8_t data, uint8_t errors);
uint8_t read_rx_fifo();
void baud_updated();
uint8_t get_chan_CSR();
// Access methods needed for 68340 serial module register model
uint8_t read_MR1(){ return MR1; }
uint8_t read_MR2(){ return MR2; }
void write_MR1(uint8_t data){ MR1 = data; }
void write_MR2(uint8_t data){ MR2 = data; }
void tx_16x_clock_w(bool state);
void rx_16x_clock_w(bool state);
int get_tx_rate() const { return tx_baud_rate; }
private:
/* Registers */
uint8_t CR; /* Command register */
uint8_t CSR; /* Clock select register */
uint8_t MR1; /* Mode register 1 */
uint8_t MR2; /* Mode register 2 */
uint8_t MR_ptr; /* Mode register pointer */
uint8_t SR; /* Status register */
/* State */
int tx_baud_rate, rx_baud_rate;
/* Receiver */
uint8_t rx_enabled;
uint16_t rx_fifo[MC68681_RX_FIFO_SIZE + 1];
int rx_fifo_read_ptr;
int rx_fifo_write_ptr;
int rx_fifo_num;
int m_ch;
/* Transmitter */
uint8_t m_tx_data;
bool m_tx_data_in_buffer;
bool m_tx_break;
uint8_t m_bits_transmitted;
bool m_tx_enabled;
/* Rx/Tx clocking */
uint8_t m_rx_prescaler , m_tx_prescaler;
duart_base_device *m_uart;
void write_MR(uint8_t data);
void write_CR(uint8_t data);
void write_TX(uint8_t data);
void recalc_framing();
};
class duart_base_device : public device_t
{
friend class duart_channel;
public:
required_device<duart_channel> m_chanA;
required_device<duart_channel> m_chanB;
optional_device<duart_channel> m_chanC;
optional_device<duart_channel> m_chanD;
// inline configuration helpers
void set_clocks(int clk3, int clk4, int clk5, int clk6);
void set_clocks(const XTAL &clk3, const XTAL &clk4, const XTAL &clk5, const XTAL &clk6) {
set_clocks(clk3.value(), clk4.value(), clk5.value(), clk6.value());
}
// API
virtual uint8_t read(offs_t offset);
virtual void write(offs_t offset, uint8_t data);
void rx_a_w(int state) { m_chanA->device_serial_interface::rx_w((uint8_t)state); }
void rx_b_w(int state) { m_chanB->device_serial_interface::rx_w((uint8_t)state); }
auto irq_cb() { return write_irq.bind(); }
auto a_tx_cb() { return write_a_tx.bind(); }
auto b_tx_cb() { return write_b_tx.bind(); }
auto inport_cb() { return read_inport.bind(); } // deprecated: use ipX_w() instead
auto outport_cb() { return write_outport.bind(); }
// new-style push handlers for input port bits
virtual void ip0_w(int state);
virtual void ip1_w(int state);
virtual void ip2_w(int state);
virtual void ip3_w(int state);
virtual void ip4_w(int state);
virtual void ip5_w(int state);
virtual void ip6_w(int state);
bool irq_pending() const { return (ISR & IMR) != 0; }
protected:
duart_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
// device-level overrides
virtual void device_start() override ATTR_COLD;
virtual void device_reset() override ATTR_COLD;
virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
devcb_write_line write_irq, write_a_tx, write_b_tx, write_c_tx, write_d_tx;
devcb_read8 read_inport;
devcb_write8 write_outport;
int32_t ip3clk, ip4clk, ip5clk, ip6clk;
protected:
virtual void update_interrupts();
private:
TIMER_CALLBACK_MEMBER(duart_timer_callback);
protected:
/* registers */
uint8_t ACR; /* Auxiliary Control Register */
uint8_t IMR; /* Interrupt Mask Register */
uint8_t ISR; /* Interrupt Status Register */
private:
uint8_t OPCR; /* Output Port Conf. Register */
uint8_t OPR; /* Output Port Register */
PAIR CTR; /* Counter/Timer Preset Value */
uint8_t IPCR; /* Input Port Control Register */
/* state */
uint8_t IP_last_state; /* last state of IP bits */
/* timer */
uint8_t half_period;
emu_timer *duart_timer;
bool m_irq_state;
uint32_t get_ct_rate();
uint16_t get_ct_count();
void start_ct(int count);
virtual int calc_baud(int ch, bool rx, uint8_t data);
void clear_ISR_bits(int mask);
void set_ISR_bits(int mask);
int get_ch(duart_channel *ch)
{
if (ch == m_chanA)
{
return 0;
}
else if (ch == m_chanB)
{
return 1;
}
else if (ch == m_chanC)
{
return 2;
}
return 3;
}
duart_channel *get_channel(int chan);
};
class scn2681_device : public duart_base_device
{
public:
scn2681_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
};
class mc68681_device : public duart_base_device
{
public:
mc68681_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
virtual uint8_t read(offs_t offset) override;
virtual void write(offs_t offset, uint8_t data) override;
uint8_t get_irq_vector();
protected:
virtual void device_start() override ATTR_COLD;
virtual void device_reset() override ATTR_COLD;
virtual void update_interrupts() override;
mc68681_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
private:
bool m_read_vector; // if this is read and IRQ is active, it counts as pulling IACK
uint8_t IVR; /* Interrupt Vector Register */
};
/**************************
* ColdFire MCF5206e UART
**************************/
class mcf5206e_uart_device : public duart_base_device
{
public:
mcf5206e_uart_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
virtual uint8_t read(offs_t offset) override;
virtual void write(offs_t offset, uint8_t data) override;
uint8_t get_irq_vector();
// There is no GPIO on the coldfire UART module
void cts_w(int state) { duart_base_device::ip0_w(state); }
virtual void ip1_w(int state) override {}
virtual void ip2_w(int state) override {}
virtual void ip3_w(int state) override {}
virtual void ip4_w(int state) override {}
virtual void ip5_w(int state) override {}
virtual void ip6_w(int state) override {}
protected:
virtual void device_start() override ATTR_COLD;
virtual void device_reset() override ATTR_COLD;
virtual void update_interrupts() override;
virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
mcf5206e_uart_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
private:
virtual int calc_baud(int ch, bool rx, uint8_t data) override;
bool m_read_vector; // if this is read and IRQ is active, it counts as pulling IACK
// ColdFire UART module is essentially two 68681 a-channels with a slighty different register map and no counter
uint8_t IVR; /* Interrupt Vector Register */
uint16_t UBG; /* Baud Rate Generator Prescale Register - Manual erronuosly calls this the timer preload register */
};
class sc28c94_device : public duart_base_device
{
public:
sc28c94_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
auto c_tx_cb() { return write_c_tx.bind(); }
auto d_tx_cb() { return write_d_tx.bind(); }
void rx_c_w(int state) { m_chanC->device_serial_interface::rx_w((uint8_t)state); }
void rx_d_w(int state) { m_chanD->device_serial_interface::rx_w((uint8_t)state); }
virtual uint8_t read(offs_t offset) override;
virtual void write(offs_t offset, uint8_t data) override;
protected:
virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
private:
};
class mc68340_duart_device : public duart_base_device
{
public:
mc68340_duart_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
virtual uint8_t read(offs_t offset) override;
virtual void write(offs_t offset, uint8_t data) override;
protected:
virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
mc68340_duart_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
private:
virtual int calc_baud(int ch, bool rx, uint8_t data) override;
};
class xr68c681_device : public mc68681_device
{
public:
xr68c681_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
virtual uint8_t read(offs_t offset) override;
virtual void write(offs_t offset, uint8_t data) override;
protected:
virtual void device_start() override ATTR_COLD;
virtual void device_reset() override ATTR_COLD;
private:
virtual int calc_baud(int ch, bool rx, uint8_t data) override;
bool m_XTXA,m_XRXA,m_XTXB,m_XRXB; /* X bits for the BRG (selects between 2 BRG tables) */
};
DECLARE_DEVICE_TYPE(SCN2681, scn2681_device)
DECLARE_DEVICE_TYPE(MC68681, mc68681_device)
DECLARE_DEVICE_TYPE(SC28C94, sc28c94_device)
DECLARE_DEVICE_TYPE(MC68340_DUART, mc68340_duart_device)
DECLARE_DEVICE_TYPE(MCF5206E_UART, mcf5206e_uart_device)
DECLARE_DEVICE_TYPE(XR68C681, xr68c681_device)
DECLARE_DEVICE_TYPE(DUART_CHANNEL, duart_channel)
#endif // MAME_MACHINE_MC68681_H