summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/m6805/m68705.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/m6805/m68705.cpp')
-rw-r--r--src/devices/cpu/m6805/m68705.cpp159
1 files changed, 103 insertions, 56 deletions
diff --git a/src/devices/cpu/m6805/m68705.cpp b/src/devices/cpu/m6805/m68705.cpp
index 814a0ca57d6..30f498980c6 100644
--- a/src/devices/cpu/m6805/m68705.cpp
+++ b/src/devices/cpu/m6805/m68705.cpp
@@ -6,7 +6,7 @@
*
* TODO
* - INT2 and miscellaneous register
- * - A/D peripheral
+ * - improve A/D peripheral
* - SPI peripheral
* - multiple timer variants
*/
@@ -20,13 +20,13 @@
* Configurable logging
****************************************************************************/
-#define LOG_GENERAL (1U << 0)
-#define LOG_INT (1U << 1)
-#define LOG_IOPORT (1U << 2)
-#define LOG_TIMER (1U << 3)
-#define LOG_EPROM (1U << 4)
+#define LOG_INT (1U << 1)
+#define LOG_IOPORT (1U << 2)
+#define LOG_TIMER (1U << 3)
+#define LOG_EPROM (1U << 4)
+#define LOG_AD (1U << 5)
-//#define VERBOSE (LOG_GENERAL | LOG_IOPORT | LOG_TIMER | LOG_EPROM)
+//#define VERBOSE (LOG_GENERAL | LOG_IOPORT | LOG_TIMER | LOG_EPROM | LOG_AD)
//#define LOG_OUTPUT_FUNC printf
#include "logmacro.h"
@@ -34,6 +34,7 @@
#define LOGIOPORT(...) LOGMASKED(LOG_IOPORT, __VA_ARGS__)
#define LOGTIMER(...) LOGMASKED(LOG_TIMER, __VA_ARGS__)
#define LOGEPROM(...) LOGMASKED(LOG_EPROM, __VA_ARGS__)
+#define LOGAD(...) LOGMASKED(LOG_AD, __VA_ARGS__)
namespace {
@@ -215,15 +216,16 @@ Ux Parts:
*/
m6805_hmos_device::m6805_hmos_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock, device_type type, u32 addr_width, unsigned ram_size)
- : m6805_base_device(mconfig, tag, owner, clock, type, { s_hmos_ops, s_hmos_cycles, addr_width, 0x007f, 0x0060, M6805_VECTOR_SWI }, address_map_constructor(FUNC(m6805_hmos_device::map), this))
+ : m6805_base_device(mconfig, tag, owner, clock, type, { addr_width > 13 ? s_hmos_b_ops : s_hmos_s_ops, s_hmos_cycles, addr_width, 0x007f, 0x0060, M6805_VECTOR_SWI }, address_map_constructor(FUNC(m6805_hmos_device::map), this))
, m_timer(*this)
, m_port_open_drain{ false, false, false, false }
, m_port_mask{ 0x00, 0x00, 0x00, 0x00 }
, m_port_input{ 0xff, 0xff, 0xff, 0xff }
, m_port_latch{ 0xff, 0xff, 0xff, 0xff }
, m_port_ddr{ 0x00, 0x00, 0x00, 0x00 }
- , m_port_cb_r(*this)
+ , m_port_cb_r(*this, 0xff)
, m_port_cb_w(*this)
+ , m_portan_cb_r(*this, 0xff)
, m_ram_size(ram_size)
{
}
@@ -231,7 +233,7 @@ m6805_hmos_device::m6805_hmos_device(machine_config const &mconfig, char const *
m68705_device::m68705_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock, device_type type, u32 addr_width, unsigned ram_size)
: m6805_hmos_device(mconfig, tag, owner, clock, type, addr_width, ram_size)
, device_nvram_interface(mconfig, *this)
- , m_user_rom(*this, DEVICE_SELF, u32(1) << addr_width)
+ , m_user_rom(*this, DEVICE_SELF)
, m_vihtp(CLEAR_LINE)
, m_pcr(0xff)
, m_pl_data(0xff)
@@ -239,7 +241,7 @@ m68705_device::m68705_device(machine_config const &mconfig, char const *tag, dev
{
}
-template <offs_t B> READ8_MEMBER(m68705_device::eprom_r)
+template <offs_t B> u8 m68705_device::eprom_r(offs_t offset)
{
if (pcr_vpon() && !pcr_ple())
LOGEPROM("read EPROM %04X prevented when Vpp high and /PLE = 0\n", B + offset);
@@ -248,7 +250,7 @@ template <offs_t B> READ8_MEMBER(m68705_device::eprom_r)
return (!pcr_vpon() || !pcr_ple()) ? m_user_rom[B + offset] : 0xff;
}
-template <offs_t B> WRITE8_MEMBER(m68705_device::eprom_w)
+template <offs_t B> void m68705_device::eprom_w(offs_t offset, u8 data)
{
LOGEPROM("EPROM programming latch write%s%s: %04X = %02X\n",
!pcr_vpon() ? " [Vpp low]" : "", !pcr_ple() ? " [disabled]" : "", B + offset, data);
@@ -281,11 +283,11 @@ template <std::size_t N> void m6805_hmos_device::set_port_mask(u8 mask)
m_port_mask[N] = mask;
}
-template <std::size_t N> READ8_MEMBER(m6805_hmos_device::port_r)
+template <std::size_t N> u8 m6805_hmos_device::port_r()
{
- if (!m_port_cb_r[N].isnull())
+ if (!m_port_cb_r[N].isunset())
{
- u8 const newval(m_port_cb_r[N](space, 0, ~m_port_ddr[N] & ~m_port_mask[N]) & ~m_port_mask[N]);
+ u8 const newval(m_port_cb_r[N](0, ~m_port_ddr[N] & ~m_port_mask[N]) & ~m_port_mask[N]);
if (newval != m_port_input[N])
{
LOGIOPORT("read PORT%c: new input = %02X & %02X (was %02X)\n",
@@ -296,7 +298,7 @@ template <std::size_t N> READ8_MEMBER(m6805_hmos_device::port_r)
return m_port_mask[N] | (m_port_latch[N] & m_port_ddr[N]) | (m_port_input[N] & ~m_port_ddr[N]);
}
-template <std::size_t N> WRITE8_MEMBER(m6805_hmos_device::port_latch_w)
+template <std::size_t N> void m6805_hmos_device::port_latch_w(u8 data)
{
data &= ~m_port_mask[N];
u8 const diff = m_port_latch[N] ^ data;
@@ -307,7 +309,7 @@ template <std::size_t N> WRITE8_MEMBER(m6805_hmos_device::port_latch_w)
port_cb_w<N>();
}
-template <std::size_t N> WRITE8_MEMBER(m6805_hmos_device::port_ddr_w)
+template <std::size_t N> void m6805_hmos_device::port_ddr_w(u8 data)
{
data &= ~m_port_mask[N];
if (data != m_port_ddr[N])
@@ -320,17 +322,17 @@ template <std::size_t N> WRITE8_MEMBER(m6805_hmos_device::port_ddr_w)
template <std::size_t N> void m6805_hmos_device::port_cb_w()
{
- u8 const data(m_port_open_drain[N] ? m_port_latch[N] | ~m_port_ddr[N] : m_port_latch[N]);
+ u8 const data(m_port_open_drain[N] ? (m_port_latch[N] | ~m_port_ddr[N]) : m_port_latch[N]);
u8 const mask(m_port_open_drain[N] ? (~m_port_latch[N] & m_port_ddr[N]) : m_port_ddr[N]);
- m_port_cb_w[N](space(AS_PROGRAM), 0, data, mask);
+ m_port_cb_w[N](0, data, mask);
}
-READ8_MEMBER(m68705_device::pcr_r)
+u8 m68705_device::pcr_r()
{
return m_pcr;
}
-WRITE8_MEMBER(m68705_device::pcr_w)
+void m68705_device::pcr_w(u8 data)
{
// 7 1
// 6 1
@@ -358,13 +360,12 @@ WRITE8_MEMBER(m68705_device::pcr_w)
m_pcr = (m_pcr & 0xfc) | (data & 0x03);
}
-READ8_MEMBER(m6805_hmos_device::acr_r)
+u8 m6805_hmos_device::acr_r()
{
- logerror("unsupported read ACR\n");
- return 0xff;
+ return m_acr_mux | 0x80 | 0x78;
}
-WRITE8_MEMBER(m6805_hmos_device::acr_w)
+void m6805_hmos_device::acr_w(u8 data)
{
// 7 conversion complete
// 6
@@ -389,18 +390,27 @@ WRITE8_MEMBER(m6805_hmos_device::acr_w)
// on completion, ACR7 is set, result is placed in ARR, and new conversion starts
// writing to ACR aborts current conversion, clears ACR7, and starts new conversion
- logerror("unsupported write ACR = %02X\n", data);
+ m_acr_mux = data & 7;
+ LOGAD("write ACR MUX = %d\n", m_acr_mux);
}
-READ8_MEMBER(m6805_hmos_device::arr_r)
+u8 m6805_hmos_device::arr_r()
{
- logerror("unsupported read ARR\n");
- return 0xff;
+ if (m_acr_mux < 4)
+ {
+ u8 val = m_portan_cb_r[m_acr_mux]();
+ LOGAD("read ARR AN%d = %02X\n", m_acr_mux, val);
+ return val;
+ }
+ else
+ {
+ logerror("unsupported read ARR VR, MUX = %d\n", m_acr_mux);
+ return 0xff;
+ }
}
-WRITE8_MEMBER(m6805_hmos_device::arr_w)
+void m6805_hmos_device::arr_w(u8 data)
{
- logerror("unsupported write ARR = %02X\n", data);
}
void m6805_hmos_device::device_start()
@@ -410,11 +420,11 @@ void m6805_hmos_device::device_start()
save_item(NAME(m_port_input));
save_item(NAME(m_port_latch));
save_item(NAME(m_port_ddr));
+ save_item(NAME(m_acr_mux));
+ save_item(NAME(m_mr));
// initialise digital I/O
for (u8 &input : m_port_input) input = 0xff;
- m_port_cb_r.resolve_all();
- m_port_cb_w.resolve_all_safe();
add_port_latch_state<0>();
add_port_latch_state<1>();
@@ -424,6 +434,10 @@ void m6805_hmos_device::device_start()
add_port_ddr_state<1>();
add_port_ddr_state<2>();
+ // initialise misc
+ m_acr_mux = 0;
+ m_mr = 0;
+
m_timer.start(M6805_PS);
}
@@ -463,15 +477,18 @@ void m6805_hmos_device::device_reset()
m6805_base_device::device_reset();
// reset digital I/O
- port_ddr_w<0>(space(AS_PROGRAM), 0, 0x00, 0xff);
- port_ddr_w<1>(space(AS_PROGRAM), 0, 0x00, 0xff);
- port_ddr_w<2>(space(AS_PROGRAM), 0, 0x00, 0xff);
- port_ddr_w<3>(space(AS_PROGRAM), 0, 0x00, 0xff);
+ port_ddr_w<0>(0x00);
+ port_ddr_w<1>(0x00);
+ port_ddr_w<2>(0x00);
+ port_ddr_w<3>(0x00);
// reset timer/counter
m_timer.reset();
- rm16(M6805_VECTOR_RESET, m_pc);
+ if (m_params.m_addr_width > 13)
+ rm16<true>(M6805_VECTOR_RESET, m_pc);
+ else
+ rm16<false>(M6805_VECTOR_RESET, m_pc);
}
void m68705_device::device_reset()
@@ -484,12 +501,18 @@ void m68705_device::device_reset()
if (CLEAR_LINE != m_vihtp)
{
LOG("loading bootstrap vector\n");
- rm16(M68705_VECTOR_BOOTSTRAP, m_pc);
+ if (m_params.m_addr_width > 13)
+ rm16<true>(M68705_VECTOR_BOOTSTRAP, m_pc);
+ else
+ rm16<false>(M68705_VECTOR_BOOTSTRAP, m_pc);
}
else
{
LOG("loading reset vector\n");
- rm16(M6805_VECTOR_RESET, m_pc);
+ if (m_params.m_addr_width > 13)
+ rm16<true>(M6805_VECTOR_RESET, m_pc);
+ else
+ rm16<false>(M6805_VECTOR_RESET, m_pc);
}
}
@@ -527,14 +550,16 @@ void m68705_device::nvram_default()
{
}
-void m68705_device::nvram_read(emu_file &file)
+bool m68705_device::nvram_read(util::read_stream &file)
{
- file.read(&m_user_rom[0], m_user_rom.bytes());
+ auto const [err, actual] = read(file, &m_user_rom[0], m_user_rom.bytes());
+ return !err && (actual == m_user_rom.bytes());
}
-void m68705_device::nvram_write(emu_file &file)
+bool m68705_device::nvram_write(util::write_stream &file)
{
- file.write(&m_user_rom[0], m_user_rom.bytes());
+ auto const [err, actual] = write(file, &m_user_rom[0], m_user_rom.bytes());
+ return !err;
}
void m6805_hmos_device::interrupt()
@@ -543,23 +568,39 @@ void m6805_hmos_device::interrupt()
{
if ((CC & IFLAG) == 0)
{
- pushword(m_pc);
- pushbyte(m_x);
- pushbyte(m_a);
- pushbyte(m_cc);
+ if (m_params.m_addr_width > 13) {
+ pushword<true>(m_pc);
+ pushbyte<true>(m_x);
+ pushbyte<true>(m_a);
+ pushbyte<true>(m_cc);
+ }
+ else
+ {
+ pushword<false>(m_pc);
+ pushbyte<false>(m_x);
+ pushbyte<false>(m_a);
+ pushbyte<false>(m_cc);
+ }
SEI;
- standard_irq_callback(0);
if (BIT(m_pending_interrupts, M6805_IRQ_LINE))
{
LOGINT("servicing /INT interrupt\n");
+ standard_irq_callback(0, m_pc.w.l);
m_pending_interrupts &= ~(1 << M6805_IRQ_LINE);
- rm16(M6805_VECTOR_INT, m_pc);
+ if (m_params.m_addr_width > 13)
+ rm16<true>(M6805_VECTOR_INT, m_pc);
+ else
+ rm16<false>(M6805_VECTOR_INT, m_pc);
}
else if (BIT(m_pending_interrupts, M6805_INT_TIMER))
{
LOGINT("servicing timer/counter interrupt\n");
- rm16(M6805_VECTOR_TIMER, m_pc);
+ standard_irq_callback(1, m_pc.w.l);
+ if (m_params.m_addr_width > 13)
+ rm16<true>(M6805_VECTOR_TIMER, m_pc);
+ else
+ rm16<false>(M6805_VECTOR_TIMER, m_pc);
}
else
{
@@ -687,8 +728,6 @@ m68705r_device::m68705r_device(machine_config const &mconfig, char const *tag, d
void m68705r_device::device_start()
{
m68705u_device::device_start();
-
- // TODO: ADC
}
std::unique_ptr<util::disasm_interface> m68705r_device::create_disassembler()
@@ -783,7 +822,8 @@ m6805p2_device::m6805p2_device(machine_config const &mconfig, char const *tag, d
* support prescalar clear, however the 1988 databook indicates the
* M6805P2 does?
*/
- //m_timer.set_options(m6805_timer::TIMER_NPC);
+ m_timer.set_options(m6805_timer::TIMER_MOR /* | m6805::TIMER_NPC */);
+ m_timer.set_source(m6805_timer::CLOCK_TIMER);
set_port_mask<2>(0xf0); // Port C is four bits wide
set_port_mask<3>(0xff); // Port D isn't present
@@ -792,6 +832,9 @@ m6805p2_device::m6805p2_device(machine_config const &mconfig, char const *tag, d
m6805p6_device::m6805p6_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock)
: m6805_mrom_device(mconfig, tag, owner, clock, M6805P6, 11, 64)
{
+ m_timer.set_options(m6805_timer::TIMER_MOR /* | m6805::TIMER_NPC */);
+ m_timer.set_source(m6805_timer::CLOCK_TIMER);
+
set_port_mask<2>(0xf0); // Port C is four bits wide
set_port_mask<3>(0xff); // Port D isn't present
}
@@ -799,6 +842,8 @@ m6805p6_device::m6805p6_device(machine_config const &mconfig, char const *tag, d
m6805r2_device::m6805r2_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock)
: m6805_mrom_device(mconfig, tag, owner, clock, M6805R2, 12, 64)
{
+ m_timer.set_options(m6805_timer::TIMER_MOR);
+ m_timer.set_source(m6805_timer::CLOCK_TIMER);
}
m6805r3_device::m6805r3_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock)
@@ -810,6 +855,8 @@ m6805r3_device::m6805r3_device(machine_config const &mconfig, char const *tag, d
m6805u2_device::m6805u2_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock)
: m6805_mrom_device(mconfig, tag, owner, clock, M6805U2, 12, 64)
{
+ m_timer.set_options(m6805_timer::TIMER_MOR);
+ m_timer.set_source(m6805_timer::CLOCK_TIMER);
}
m6805u3_device::m6805u3_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock)
@@ -898,7 +945,7 @@ void m6805_mrom_device::internal_map(address_map &map)
void m6805r2_device::internal_map(address_map &map)
{
- m6805_hmos_device::internal_map(map);
+ m6805_mrom_device::internal_map(map);
map(0x000e, 0x000e).rw(FUNC(m6805r2_device::acr_r), FUNC(m6805r2_device::acr_w));
map(0x000f, 0x000f).rw(FUNC(m6805r2_device::arr_r), FUNC(m6805r2_device::arr_w));
@@ -906,7 +953,7 @@ void m6805r2_device::internal_map(address_map &map)
void m6805r3_device::internal_map(address_map &map)
{
- m6805_hmos_device::internal_map(map);
+ m6805_mrom_device::internal_map(map);
map(0x000e, 0x000e).rw(FUNC(m6805r3_device::acr_r), FUNC(m6805r3_device::acr_w));
map(0x000f, 0x000f).rw(FUNC(m6805r3_device::arr_r), FUNC(m6805r3_device::arr_w));