summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--src/emu/cpu/upd7810/upd7810.c118
-rw-r--r--src/emu/cpu/upd7810/upd7810.h48
2 files changed, 166 insertions, 0 deletions
diff --git a/src/emu/cpu/upd7810/upd7810.c b/src/emu/cpu/upd7810/upd7810.c
index 04e11049150..4e45f2cb436 100644
--- a/src/emu/cpu/upd7810/upd7810.c
+++ b/src/emu/cpu/upd7810/upd7810.c
@@ -421,6 +421,14 @@ upd7810_device::upd7810_device(const machine_config &mconfig, const char *tag, d
, m_to_func(*this)
, m_txd_func(*this)
, m_rxd_func(*this)
+ , m_an0_func(*this)
+ , m_an1_func(*this)
+ , m_an2_func(*this)
+ , m_an3_func(*this)
+ , m_an4_func(*this)
+ , m_an5_func(*this)
+ , m_an6_func(*this)
+ , m_an7_func(*this)
, m_program_config("program", ENDIANNESS_LITTLE, 8, 16, 0)
, m_io_config("io", ENDIANNESS_LITTLE, 8, 8, 0)
{
@@ -439,6 +447,14 @@ upd7810_device::upd7810_device(const machine_config &mconfig, device_type type,
, m_to_func(*this)
, m_txd_func(*this)
, m_rxd_func(*this)
+ , m_an0_func(*this)
+ , m_an1_func(*this)
+ , m_an2_func(*this)
+ , m_an3_func(*this)
+ , m_an4_func(*this)
+ , m_an5_func(*this)
+ , m_an6_func(*this)
+ , m_an7_func(*this)
, m_program_config("program", ENDIANNESS_LITTLE, 8, 16, 0)
, m_io_config("io", ENDIANNESS_LITTLE, 8, 8, 0)
{
@@ -620,6 +636,7 @@ offs_t upd78c05_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8
#define EOM m_eom
#define SML m_sml
#define SMH m_smh
+#define PANM m_panm
#define ANM m_anm
#define MKL m_mkl
#define MKH m_mkh
@@ -1634,6 +1651,93 @@ void upd7810_device::handle_timers(int cycles)
}
break;
}
+
+ /**** ADC ****/
+ m_adcnt += cycles;
+ if (PANM != ANM)
+ {
+ /* reset A/D converter */
+ m_adcnt = 0;
+ if (ANM & 0x10)
+ m_adtot = 144;
+ else
+ m_adtot = 192;
+ m_adout = 0;
+ if (ANM & 0x01)
+ {
+ /* select mode */
+ m_adin = (ANM >> 1) & 0x07;
+ }
+ else
+ {
+ /* scan mode */
+ m_adin = 0;
+ m_adrange = (ANM >> 1) & 0x04;
+ }
+ }
+ PANM = ANM;
+ if (ANM & 0x01)
+ {
+ /* select mode */
+ while (m_adcnt > m_adtot)
+ {
+ UINT8 cr = 0;
+ m_adcnt -= m_adtot;
+ switch (m_adin)
+ {
+ case 0: cr = m_an0_func(); break;
+ case 1: cr = m_an1_func(); break;
+ case 2: cr = m_an2_func(); break;
+ case 3: cr = m_an3_func(); break;
+ case 4: cr = m_an4_func(); break;
+ case 5: cr = m_an5_func(); break;
+ case 6: cr = m_an6_func(); break;
+ case 7: cr = m_an7_func(); break;
+ }
+ switch (m_adout)
+ {
+ case 0: CR0 = cr; break;
+ case 1: CR1 = cr; break;
+ case 2: CR2 = cr; break;
+ case 3: CR3 = cr; break;
+ }
+ m_adout = (m_adout + 1) & 0x07;
+ if (m_adout == 0)
+ IRR |= INTFAD;
+ }
+ }
+ else
+ {
+ /* scan mode */
+ while (m_adcnt > m_adtot)
+ {
+ UINT8 cr = 0;
+ m_adcnt -= m_adtot;
+ switch (m_adin | m_adrange)
+ {
+ case 0: cr = m_an0_func(); break;
+ case 1: cr = m_an1_func(); break;
+ case 2: cr = m_an2_func(); break;
+ case 3: cr = m_an3_func(); break;
+ case 4: cr = m_an4_func(); break;
+ case 5: cr = m_an5_func(); break;
+ case 6: cr = m_an6_func(); break;
+ case 7: cr = m_an7_func(); break;
+ }
+ switch (m_adout)
+ {
+ case 0: CR0 = cr; break;
+ case 1: CR1 = cr; break;
+ case 2: CR2 = cr; break;
+ case 3: CR3 = cr; break;
+ }
+ m_adin = (m_adin + 1) & 0x07;
+ m_adout = (m_adout + 1) & 0x07;
+ if (m_adout == 0)
+ IRR |= INTFAD;
+ }
+ }
+
}
void upd7801_device::handle_timers(int cycles)
@@ -1685,6 +1789,14 @@ void upd7810_device::base_device_start()
m_to_func.resolve_safe();
m_txd_func.resolve_safe();
m_rxd_func.resolve_safe(0);
+ m_an0_func.resolve_safe(0);
+ m_an1_func.resolve_safe(0);
+ m_an2_func.resolve_safe(0);
+ m_an3_func.resolve_safe(0);
+ m_an4_func.resolve_safe(0);
+ m_an5_func.resolve_safe(0);
+ m_an6_func.resolve_safe(0);
+ m_an7_func.resolve_safe(0);
save_item(NAME(m_ppc.w.l));
save_item(NAME(m_pc.w.l));
@@ -1946,7 +2058,13 @@ void upd7810_device::device_reset()
m_ovcf = 0;
m_ovcs = 0;
m_edges = 0;
+ m_adcnt = 0;
+ m_adtot = 0;
+ m_adout = 0;
+ m_adin = 0;
+ m_adrange = 0;
+ PANM = 0xff;
ETMM = 0xff;
TMM = 0xff;
MA = 0xff;
diff --git a/src/emu/cpu/upd7810/upd7810.h b/src/emu/cpu/upd7810/upd7810.h
index f73d3df8d7c..270152e966c 100644
--- a/src/emu/cpu/upd7810/upd7810.h
+++ b/src/emu/cpu/upd7810/upd7810.h
@@ -23,6 +23,7 @@ enum
UPD7810_TMM, UPD7810_ETMM, UPD7810_EOM, UPD7810_SML, UPD7810_SMH,
UPD7810_ANM, UPD7810_MKL, UPD7810_MKH, UPD7810_ZCM,
UPD7810_TXB, UPD7810_RXB, UPD7810_CR0, UPD7810_CR1, UPD7810_CR2, UPD7810_CR3,
+ UPD7810_AN0, UPD7810_AN1, UPD7810_AN2, UPD7810_AN3, UPD7810_AN4, UPD7810_AN5, UPD7810_AN6, UPD7810_AN7,
UPD7810_TXD, UPD7810_RXD, UPD7810_SCK, UPD7810_TI, UPD7810_TO, UPD7810_CI, UPD7810_CO0, UPD7810_CO1
};
@@ -55,6 +56,31 @@ enum
#define MCFG_UPD7810_RXD(_devcb) \
upd7810_device::set_rxd_func(*device, DEVCB2_##_devcb);
+#define MCFG_UPD7810_AN0(_devcb) \
+ upd7810_device::set_an0_func(*device, DEVCB2_##_devcb);
+
+#define MCFG_UPD7810_AN1(_devcb) \
+ upd7810_device::set_an1_func(*device, DEVCB2_##_devcb);
+
+#define MCFG_UPD7810_AN2(_devcb) \
+ upd7810_device::set_an2_func(*device, DEVCB2_##_devcb);
+
+#define MCFG_UPD7810_AN3(_devcb) \
+ upd7810_device::set_an3_func(*device, DEVCB2_##_devcb);
+
+#define MCFG_UPD7810_AN4(_devcb) \
+ upd7810_device::set_an4_func(*device, DEVCB2_##_devcb);
+
+#define MCFG_UPD7810_AN5(_devcb) \
+ upd7810_device::set_an5_func(*device, DEVCB2_##_devcb);
+
+#define MCFG_UPD7810_AN6(_devcb) \
+ upd7810_device::set_an6_func(*device, DEVCB2_##_devcb);
+
+#define MCFG_UPD7810_AN7(_devcb) \
+ upd7810_device::set_an7_func(*device, DEVCB2_##_devcb);
+
+
class upd7810_device : public cpu_device
{
public:
@@ -66,6 +92,14 @@ public:
template<class _Object> static devcb2_base &set_to_func(device_t &device, _Object object) { return downcast<upd7810_device &>(device).m_to_func.set_callback(object); }
template<class _Object> static devcb2_base &set_txd_func(device_t &device, _Object object) { return downcast<upd7810_device &>(device).m_txd_func.set_callback(object); }
template<class _Object> static devcb2_base &set_rxd_func(device_t &device, _Object object) { return downcast<upd7810_device &>(device).m_rxd_func.set_callback(object); }
+ template<class _Object> static devcb2_base &set_an0_func(device_t &device, _Object object) { return downcast<upd7810_device &>(device).m_an0_func.set_callback(object); }
+ template<class _Object> static devcb2_base &set_an1_func(device_t &device, _Object object) { return downcast<upd7810_device &>(device).m_an1_func.set_callback(object); }
+ template<class _Object> static devcb2_base &set_an2_func(device_t &device, _Object object) { return downcast<upd7810_device &>(device).m_an2_func.set_callback(object); }
+ template<class _Object> static devcb2_base &set_an3_func(device_t &device, _Object object) { return downcast<upd7810_device &>(device).m_an3_func.set_callback(object); }
+ template<class _Object> static devcb2_base &set_an4_func(device_t &device, _Object object) { return downcast<upd7810_device &>(device).m_an4_func.set_callback(object); }
+ template<class _Object> static devcb2_base &set_an5_func(device_t &device, _Object object) { return downcast<upd7810_device &>(device).m_an5_func.set_callback(object); }
+ template<class _Object> static devcb2_base &set_an6_func(device_t &device, _Object object) { return downcast<upd7810_device &>(device).m_an6_func.set_callback(object); }
+ template<class _Object> static devcb2_base &set_an7_func(device_t &device, _Object object) { return downcast<upd7810_device &>(device).m_an7_func.set_callback(object); }
protected:
// device-level overrides
@@ -96,6 +130,14 @@ protected:
devcb2_write_line m_to_func;
devcb2_write_line m_txd_func;
devcb2_read_line m_rxd_func;
+ devcb2_read_line m_an0_func;
+ devcb2_read_line m_an1_func;
+ devcb2_read_line m_an2_func;
+ devcb2_read_line m_an3_func;
+ devcb2_read_line m_an4_func;
+ devcb2_read_line m_an5_func;
+ devcb2_read_line m_an6_func;
+ devcb2_read_line m_an7_func;
typedef void (upd7810_device::*opcode_func)();
@@ -176,6 +218,7 @@ protected:
UINT8 m_eom; /* 16-bit timer/event counter output control */
UINT8 m_sml; /* serial interface parameters low */
UINT8 m_smh; /* -"- high */
+ UINT8 m_panm; /* previous analog to digital converter operating parameters */
UINT8 m_anm; /* analog to digital converter operating parameters */
UINT8 m_mkl; /* interrupt mask low */
UINT8 m_mkh; /* -"- high */
@@ -221,6 +264,11 @@ protected:
INT32 m_ovcf; /* overflow counter for fixed clock div 3 mode */
INT32 m_ovcs; /* overflow counter for serial I/O */
UINT8 m_edges; /* rising/falling edge flag for serial I/O */
+ UINT16 m_adcnt; /* A/D converter cycle count */
+ UINT8 m_adtot; /* A/D converter total cycles per conversion */
+ int m_adout; /* currently selected A/D converter output register */
+ int m_adin; /* currently selected A/D converter input */
+ int m_adrange;/* in scan mode, A/D converter range (AN0-AN3 or AN4-AN7) */
const struct opcode_s *m_opXX; /* opcode table */
const struct opcode_s *m_op48;