Merge pull request #25 from ramiropolla/upd7810

upd7810: Some fixes and code simplification
This commit is contained in:
Miodrag Milanović 2014-10-31 08:55:54 +01:00
commit d5fa81a5db
2 changed files with 154 additions and 244 deletions

View File

@ -1174,6 +1174,64 @@ void upd7810_device::upd7810_sio_input()
}
}
void upd7810_device::upd7810_handle_timer0(int cycles, int clkdiv)
{
OVC0 += cycles;
while (OVC0 >= clkdiv)
{
OVC0 -= clkdiv;
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)
{
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 ****/
@ -1184,74 +1242,10 @@ void upd7810_device::handle_timers(int cycles)
switch (TMM & 0x0c) /* timer 0 clock source */
{
case 0x00: /* clock divided by 12 */
OVC0 += cycles;
while (OVC0 >= 12)
{
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);
}
}
}
}
}
upd7810_handle_timer0(cycles, 12);
break;
case 0x04: /* clock divided by 384 */
OVC0 += cycles;
while (OVC0 >= 384)
{
OVC0 -= 384;
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)
{
CNT1 = 0;
IRR |= INTFT1;
/* timer F/F source is timer 1 ? */
if (0x01 == (TMM & 0x03))
{
TO ^= 1;
m_to_func(TO);
}
}
}
}
}
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,10 +1321,11 @@ void upd7810_device::handle_timers(int cycles)
ECNT = 0;
break;
}
switch (ETMM & 0x30)
{
case 0x00: /* set CO0 if ECNT == ETM0 */
if (ETM0 == ECNT)
/* 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 */
{
switch (EOM & 0x0e)
{
@ -1371,48 +1340,11 @@ void upd7810_device::handle_timers(int cycles)
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)
{
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)
{
case 0x00: /* lacth CO1 if ECNT == ETM1 */
if (ETM1 == ECNT)
/* 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 */
{
switch (EOM & 0xe0)
{
@ -1427,44 +1359,6 @@ void upd7810_device::handle_timers(int cycles)
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)
{
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;
}
}
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;

View File

@ -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) */