summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Miodrag Milanović <mmicko@gmail.com>2014-10-31 08:55:54 +0100
committer Miodrag Milanović <mmicko@gmail.com>2014-10-31 08:55:54 +0100
commitd5fa81a5db1033b18ce7adf17d8aad5d6808f67a (patch)
tree7c0bab8bb083abc8437d066b1bd09c52b57e71b6
parent237af493d3238f7a38059b9eab9f224c860f9eec (diff)
parent8d227004875941aae47ce9dff30cb25483b25f7b (diff)
Merge pull request #25 from ramiropolla/upd7810
upd7810: Some fixes and code simplification
-rw-r--r--src/emu/cpu/upd7810/upd7810.c375
-rw-r--r--src/emu/cpu/upd7810/upd7810.h21
2 files changed, 153 insertions, 243 deletions
diff --git a/src/emu/cpu/upd7810/upd7810.c b/src/emu/cpu/upd7810/upd7810.c
index 1232fd20271..bc62fa33ffa 100644
--- a/src/emu/cpu/upd7810/upd7810.c
+++ b/src/emu/cpu/upd7810/upd7810.c
@@ -1174,84 +1174,78 @@ void upd7810_device::upd7810_sio_input()
}
}
-void upd7810_device::handle_timers(int cycles)
+void upd7810_device::upd7810_handle_timer0(int cycles, int clkdiv)
{
- /**** TIMER 0 ****/
- if (TMM & 0x10) /* timer 0 upcounter reset ? */
- CNT0 = 0;
- else
+ OVC0 += cycles;
+ while (OVC0 >= clkdiv)
{
- switch (TMM & 0x0c) /* timer 0 clock source */
+ OVC0 -= clkdiv;
+ CNT0++;
+ if (CNT0 == TM0)
{
- case 0x00: /* clock divided by 12 */
- OVC0 += cycles;
- while (OVC0 >= 12)
+ CNT0 = 0;
+ IRR |= INTFT0;
+ /* timer F/F source is timer 0 ? */
+ if (0x00 == (TMM & 0x03))
{
- OVC0 -= 12;
- CNT0++;
- if (CNT0 == TM0)
- {
- CNT0 = 0;
- IRR |= INTFT0;
- /* timer F/F source is timer 0 ? */
- if (0x00 == (TMM & 0x03))
- {
- TO ^= 1;
- m_to_func(TO);
- }
- /* timer 1 chained with timer 0 ? */
- if ((TMM & 0xe0) == 0x60)
- {
- CNT1++;
- if (CNT1 == TM1)
- {
- IRR |= INTFT1;
- CNT1 = 0;
- /* timer F/F source is timer 1 ? */
- if (0x01 == (TMM & 0x03))
- {
- TO ^= 1;
- m_to_func(TO);
- }
- }
- }
- }
+ TO ^= 1;
+ m_to_func(TO);
}
- break;
- case 0x04: /* clock divided by 384 */
- OVC0 += cycles;
- while (OVC0 >= 384)
+ /* timer 1 chained with timer 0 ? */
+ if ((TMM & 0xe0) == 0x60)
{
- OVC0 -= 384;
- CNT0++;
- if (CNT0 == TM0)
+ CNT1++;
+ if (CNT1 == TM1)
{
- CNT0 = 0;
- IRR |= INTFT0;
- /* timer F/F source is timer 0 ? */
- if (0x00 == (TMM & 0x03))
+ CNT1 = 0;
+ IRR |= INTFT1;
+ /* timer F/F source is timer 1 ? */
+ if (0x01 == (TMM & 0x03))
{
TO ^= 1;
m_to_func(TO);
}
- /* timer 1 chained with timer 0 ? */
- if ((TMM & 0xe0) == 0x60)
- {
- CNT1++;
- if (CNT1 == TM1)
- {
- CNT1 = 0;
- IRR |= INTFT1;
- /* timer F/F source is timer 1 ? */
- if (0x01 == (TMM & 0x03))
- {
- TO ^= 1;
- m_to_func(TO);
- }
- }
- }
}
}
+ }
+ }
+}
+
+void upd7810_device::upd7810_handle_timer1(int cycles, int clkdiv)
+{
+ OVC1 += cycles;
+ while (OVC1 >= clkdiv)
+ {
+ OVC1 -= clkdiv;
+ CNT1++;
+ if (CNT1 == TM1)
+ {
+ CNT1 = 0;
+ IRR |= INTFT1;
+ /* timer F/F source is timer 1 ? */
+ if (0x01 == (TMM & 0x03))
+ {
+ TO ^= 1;
+ m_to_func(TO);
+ }
+ }
+ }
+}
+
+void upd7810_device::handle_timers(int cycles)
+{
+ /**** TIMER 0 ****/
+ if (TMM & 0x10) /* timer 0 upcounter reset ? */
+ CNT0 = 0;
+ else
+ {
+ switch (TMM & 0x0c) /* timer 0 clock source */
+ {
+ case 0x00: /* clock divided by 12 */
+ upd7810_handle_timer0(cycles, 12);
+ break;
+ case 0x04: /* clock divided by 384 */
+ upd7810_handle_timer0(cycles, 384);
break;
case 0x08: /* external signal at TI */
break;
@@ -1268,42 +1262,10 @@ void upd7810_device::handle_timers(int cycles)
switch (TMM & 0x60) /* timer 1 clock source */
{
case 0x00: /* clock divided by 12 */
- OVC1 += cycles;
- while (OVC1 >= 12)
- {
- OVC1 -= 12;
- CNT1++;
- if (CNT1 == TM1)
- {
- CNT1 = 0;
- IRR |= INTFT1;
- /* timer F/F source is timer 1 ? */
- if (0x01 == (TMM & 0x03))
- {
- TO ^= 1;
- m_to_func(TO);
- }
- }
- }
+ upd7810_handle_timer1(cycles, 12);
break;
case 0x20: /* clock divided by 384 */
- OVC1 += cycles;
- while (OVC1 >= 384)
- {
- OVC1 -= 384;
- CNT1++;
- if (CNT1 == TM1)
- {
- CNT1 = 0;
- IRR |= INTFT1;
- /* timer F/F source is timer 1 ? */
- if (0x01 == (TMM & 0x03))
- {
- TO ^= 1;
- m_to_func(TO);
- }
- }
- }
+ upd7810_handle_timer1(cycles, 384);
break;
case 0x40: /* external signal at TI */
break;
@@ -1338,6 +1300,12 @@ void upd7810_device::handle_timers(int cycles)
{
OVCE -= 12;
ECNT++;
+ /* Interrupt Control Circuit */
+ if (ETM0 == ECNT)
+ IRR |= INTFE0;
+ if (ETM1 == ECNT)
+ IRR |= INTFE1;
+ /* How and When ECNT is Cleared */
switch (ETMM & 0x0c)
{
case 0x00: /* clear ECNT */
@@ -1353,117 +1321,43 @@ void upd7810_device::handle_timers(int cycles)
ECNT = 0;
break;
}
- switch (ETMM & 0x30)
+ /* Conditions When ECNT Causes a CO0 Output Change */
+ if (((0x00 == (ETMM & 0x30)) && (ETM0 == ECNT)) || /* set CO0 if ECNT == ETM0 */
+ /* ((0x10 == (ETMM & 0x30)) prohibited */
+ ((0x20 == (ETMM & 0x30)) && (ETM0 == ECNT)) || /* set CO0 if ECNT == ETM0 or at falling CI input */
+ ((0x30 == (ETMM & 0x30)) && (ETM0 == ECNT || ETM1 == ECNT))) /* latch CO0 if ECNT == ETM0 or ECNT == ETM1 */
{
- case 0x00: /* set CO0 if ECNT == ETM0 */
- if (ETM0 == ECNT)
- {
- switch (EOM & 0x0e)
- {
- case 0x02: /* toggle CO0 */
- CO0 = (CO0 >> 1) | ((CO0 ^ 2) & 2);
- break;
- case 0x04: /* reset CO0 */
- CO0 = 0;
- break;
- case 0x08: /* set CO0 */
- CO0 = 1;
- break;
- }
- }
- break;
- case 0x10: /* prohibited */
- break;
- case 0x20: /* set CO0 if ECNT == ETM0 or at falling CI input */
- if (ETM0 == ECNT)
- {
- switch (EOM & 0x0e)
- {
- case 0x02: /* toggle CO0 */
- CO0 = (CO0 >> 1) | ((CO0 ^ 2) & 2);
- break;
- case 0x04: /* reset CO0 */
- CO0 = 0;
- break;
- case 0x08: /* set CO0 */
- CO0 = 1;
- break;
- }
- }
- break;
- case 0x30: /* latch CO0 if ECNT == ETM0 or ECNT == ETM1 */
- if (ETM0 == ECNT || ETM1 == ECNT)
+ switch (EOM & 0x0e)
{
- switch (EOM & 0x0e)
- {
- case 0x02: /* toggle CO0 */
- CO0 = (CO0 >> 1) | ((CO0 ^ 2) & 2);
- break;
- case 0x04: /* reset CO0 */
- CO0 = 0;
- break;
- case 0x08: /* set CO0 */
- CO0 = 1;
- break;
- }
+ case 0x02: /* toggle CO0 */
+ CO0 = (CO0 >> 1) | ((CO0 ^ 2) & 2);
+ break;
+ case 0x04: /* reset CO0 */
+ CO0 = 0;
+ break;
+ case 0x08: /* set CO0 */
+ CO0 = 1;
+ break;
}
- break;
}
- switch (ETMM & 0xc0)
+ /* Conditions When ECNT Causes a CO1 Output Change */
+ if (((0x00 == (ETMM & 0xc0)) && (ETM0 == ECNT)) || /* set CO1 if ECNT == ETM0 */
+ /* ((0x40 == (ETMM & 0xc0)) prohibited */
+ ((0x80 == (ETMM & 0xc0)) && (ETM0 == ECNT)) || /* set CO1 if ECNT == ETM0 or at falling CI input */
+ ((0xc0 == (ETMM & 0xc0)) && (ETM0 == ECNT || ETM1 == ECNT))) /* latch CO1 if ECNT == ETM0 or ECNT == ETM1 */
{
- case 0x00: /* lacth CO1 if ECNT == ETM1 */
- if (ETM1 == ECNT)
- {
- switch (EOM & 0xe0)
- {
- case 0x20: /* toggle CO1 */
- CO1 = (CO1 >> 1) | ((CO1 ^ 2) & 2);
- break;
- case 0x40: /* reset CO1 */
- CO1 = 0;
- break;
- case 0x80: /* set CO1 */
- CO1 = 1;
- break;
- }
- }
- break;
- case 0x40: /* prohibited */
- break;
- case 0x80: /* latch CO1 if ECNT == ETM1 or falling edge of CI input */
- if (ETM1 == ECNT)
+ switch (EOM & 0xe0)
{
- switch (EOM & 0xe0)
- {
- case 0x20: /* toggle CO1 */
- CO1 = (CO1 >> 1) | ((CO1 ^ 2) & 2);
- break;
- case 0x40: /* reset CO1 */
- CO1 = 0;
- break;
- case 0x80: /* set CO1 */
- CO1 = 1;
- break;
- }
- }
- break;
- case 0xc0: /* latch CO1 if ECNT == ETM0 or ECNT == ETM1 */
- if (ETM0 == ECNT || ETM1 == ECNT)
- {
- switch (EOM & 0xe0)
- {
- case 0x20: /* toggle CO1 */
- CO1 = (CO1 >> 1) | ((CO1 ^ 2) & 2);
- break;
- case 0x40: /* reset CO1 */
- CO1 = 0;
- break;
- case 0x80: /* set CO1 */
- CO1 = 1;
- break;
- }
+ case 0x20: /* toggle CO1 */
+ CO1 = (CO1 >> 1) | ((CO1 ^ 2) & 2);
+ break;
+ case 0x40: /* reset CO1 */
+ CO1 = 0;
+ break;
+ case 0x80: /* set CO1 */
+ CO1 = 1;
+ break;
}
- break;
}
}
}
@@ -1508,6 +1402,7 @@ void upd7810_device::handle_timers(int cycles)
else
m_adtot = 192;
m_adout = 0;
+ m_shdone = 0;
if (ANM & 0x01)
{
/* select mode */
@@ -1524,62 +1419,70 @@ void upd7810_device::handle_timers(int cycles)
if (ANM & 0x01)
{
/* select mode */
- while (m_adcnt > m_adtot)
+ if (m_shdone == 0)
{
- 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;
+ case 0: m_tmpcr = m_an0_func(); break;
+ case 1: m_tmpcr = m_an1_func(); break;
+ case 2: m_tmpcr = m_an2_func(); break;
+ case 3: m_tmpcr = m_an3_func(); break;
+ case 4: m_tmpcr = m_an4_func(); break;
+ case 5: m_tmpcr = m_an5_func(); break;
+ case 6: m_tmpcr = m_an6_func(); break;
+ case 7: m_tmpcr = m_an7_func(); break;
}
+ m_shdone = 1;
+ }
+ if (m_adcnt > m_adtot)
+ {
+ m_adcnt -= m_adtot;
switch (m_adout)
{
- case 0: CR0 = cr; break;
- case 1: CR1 = cr; break;
- case 2: CR2 = cr; break;
- case 3: CR3 = cr; break;
+ case 0: CR0 = m_tmpcr; break;
+ case 1: CR1 = m_tmpcr; break;
+ case 2: CR2 = m_tmpcr; break;
+ case 3: CR3 = m_tmpcr; break;
}
- m_adout = (m_adout + 1) & 0x07;
+ m_adout = (m_adout + 1) & 0x03;
if (m_adout == 0)
IRR |= INTFAD;
+ m_shdone = 0;
}
}
else
{
/* scan mode */
- while (m_adcnt > m_adtot)
+ if (m_shdone == 0)
{
- 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;
+ case 0: m_tmpcr = m_an0_func(); break;
+ case 1: m_tmpcr = m_an1_func(); break;
+ case 2: m_tmpcr = m_an2_func(); break;
+ case 3: m_tmpcr = m_an3_func(); break;
+ case 4: m_tmpcr = m_an4_func(); break;
+ case 5: m_tmpcr = m_an5_func(); break;
+ case 6: m_tmpcr = m_an6_func(); break;
+ case 7: m_tmpcr = m_an7_func(); break;
}
+ m_shdone = 1;
+ }
+ if (m_adcnt > m_adtot)
+ {
+ m_adcnt -= m_adtot;
switch (m_adout)
{
- case 0: CR0 = cr; break;
- case 1: CR1 = cr; break;
- case 2: CR2 = cr; break;
- case 3: CR3 = cr; break;
+ case 0: CR0 = m_tmpcr; break;
+ case 1: CR1 = m_tmpcr; break;
+ case 2: CR2 = m_tmpcr; break;
+ case 3: CR3 = m_tmpcr; break;
}
m_adin = (m_adin + 1) & 0x07;
- m_adout = (m_adout + 1) & 0x07;
+ m_adout = (m_adout + 1) & 0x03;
if (m_adout == 0)
IRR |= INTFAD;
+ m_shdone = 0;
}
}
@@ -1902,6 +1805,8 @@ void upd7810_device::device_reset()
m_edges = 0;
m_adcnt = 0;
m_adtot = 0;
+ m_tmpcr = 0;
+ m_shdone = 0;
m_adout = 0;
m_adin = 0;
m_adrange = 0;
diff --git a/src/emu/cpu/upd7810/upd7810.h b/src/emu/cpu/upd7810/upd7810.h
index 3be3177040c..f975c88c7c7 100644
--- a/src/emu/cpu/upd7810/upd7810.h
+++ b/src/emu/cpu/upd7810/upd7810.h
@@ -169,17 +169,20 @@ protected:
virtual void handle_timers(int cycles);
virtual void upd7810_take_irq();
+ void upd7810_handle_timer0(int cycles, int clkdiv);
+ void upd7810_handle_timer1(int cycles, int clkdiv);
+
devcb_write_line m_to_func;
devcb_write_line m_txd_func;
devcb_read_line m_rxd_func;
- devcb_read_line m_an0_func;
- devcb_read_line m_an1_func;
- devcb_read_line m_an2_func;
- devcb_read_line m_an3_func;
- devcb_read_line m_an4_func;
- devcb_read_line m_an5_func;
- devcb_read_line m_an6_func;
- devcb_read_line m_an7_func;
+ devcb_read8 m_an0_func;
+ devcb_read8 m_an1_func;
+ devcb_read8 m_an2_func;
+ devcb_read8 m_an3_func;
+ devcb_read8 m_an4_func;
+ devcb_read8 m_an5_func;
+ devcb_read8 m_an6_func;
+ devcb_read8 m_an7_func;
typedef void (upd7810_device::*opcode_func)();
@@ -308,6 +311,8 @@ protected:
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 */
+ UINT8 m_tmpcr; /* temporary analog digital conversion register */
+ int m_shdone; /* A/D converter sample and hold done */
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) */