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) void upd7810_device::handle_timers(int cycles)
{ {
/**** TIMER 0 ****/ /**** TIMER 0 ****/
@ -1184,74 +1242,10 @@ void upd7810_device::handle_timers(int cycles)
switch (TMM & 0x0c) /* timer 0 clock source */ switch (TMM & 0x0c) /* timer 0 clock source */
{ {
case 0x00: /* clock divided by 12 */ case 0x00: /* clock divided by 12 */
OVC0 += cycles; upd7810_handle_timer0(cycles, 12);
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);
}
}
}
}
}
break; break;
case 0x04: /* clock divided by 384 */ case 0x04: /* clock divided by 384 */
OVC0 += cycles; upd7810_handle_timer0(cycles, 384);
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);
}
}
}
}
}
break; break;
case 0x08: /* external signal at TI */ case 0x08: /* external signal at TI */
break; break;
@ -1268,42 +1262,10 @@ void upd7810_device::handle_timers(int cycles)
switch (TMM & 0x60) /* timer 1 clock source */ switch (TMM & 0x60) /* timer 1 clock source */
{ {
case 0x00: /* clock divided by 12 */ case 0x00: /* clock divided by 12 */
OVC1 += cycles; upd7810_handle_timer1(cycles, 12);
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);
}
}
}
break; break;
case 0x20: /* clock divided by 384 */ case 0x20: /* clock divided by 384 */
OVC1 += cycles; upd7810_handle_timer1(cycles, 384);
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);
}
}
}
break; break;
case 0x40: /* external signal at TI */ case 0x40: /* external signal at TI */
break; break;
@ -1338,6 +1300,12 @@ void upd7810_device::handle_timers(int cycles)
{ {
OVCE -= 12; OVCE -= 12;
ECNT++; ECNT++;
/* Interrupt Control Circuit */
if (ETM0 == ECNT)
IRR |= INTFE0;
if (ETM1 == ECNT)
IRR |= INTFE1;
/* How and When ECNT is Cleared */
switch (ETMM & 0x0c) switch (ETMM & 0x0c)
{ {
case 0x00: /* clear ECNT */ case 0x00: /* clear ECNT */
@ -1353,10 +1321,11 @@ void upd7810_device::handle_timers(int cycles)
ECNT = 0; ECNT = 0;
break; break;
} }
switch (ETMM & 0x30) /* Conditions When ECNT Causes a CO0 Output Change */
{ if (((0x00 == (ETMM & 0x30)) && (ETM0 == ECNT)) || /* set CO0 if ECNT == ETM0 */
case 0x00: /* set CO0 if ECNT == ETM0 */ /* ((0x10 == (ETMM & 0x30)) prohibited */
if (ETM0 == ECNT) ((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) switch (EOM & 0x0e)
{ {
@ -1371,48 +1340,11 @@ void upd7810_device::handle_timers(int cycles)
break; break;
} }
} }
break; /* Conditions When ECNT Causes a CO1 Output Change */
case 0x10: /* prohibited */ if (((0x00 == (ETMM & 0xc0)) && (ETM0 == ECNT)) || /* set CO1 if ECNT == ETM0 */
break; /* ((0x40 == (ETMM & 0xc0)) prohibited */
case 0x20: /* set CO0 if ECNT == ETM0 or at falling CI input */ ((0x80 == (ETMM & 0xc0)) && (ETM0 == ECNT)) || /* set CO1 if ECNT == ETM0 or at falling CI input */
if (ETM0 == ECNT) ((0xc0 == (ETMM & 0xc0)) && (ETM0 == ECNT || ETM1 == ECNT))) /* latch CO1 if ECNT == ETM0 or ECNT == ETM1 */
{
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)
{ {
switch (EOM & 0xe0) switch (EOM & 0xe0)
{ {
@ -1427,44 +1359,6 @@ void upd7810_device::handle_timers(int cycles)
break; 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 else
m_adtot = 192; m_adtot = 192;
m_adout = 0; m_adout = 0;
m_shdone = 0;
if (ANM & 0x01) if (ANM & 0x01)
{ {
/* select mode */ /* select mode */
@ -1524,62 +1419,70 @@ void upd7810_device::handle_timers(int cycles)
if (ANM & 0x01) if (ANM & 0x01)
{ {
/* select mode */ /* select mode */
while (m_adcnt > m_adtot) if (m_shdone == 0)
{ {
UINT8 cr = 0;
m_adcnt -= m_adtot;
switch (m_adin) switch (m_adin)
{ {
case 0: cr = m_an0_func(); break; case 0: m_tmpcr = m_an0_func(); break;
case 1: cr = m_an1_func(); break; case 1: m_tmpcr = m_an1_func(); break;
case 2: cr = m_an2_func(); break; case 2: m_tmpcr = m_an2_func(); break;
case 3: cr = m_an3_func(); break; case 3: m_tmpcr = m_an3_func(); break;
case 4: cr = m_an4_func(); break; case 4: m_tmpcr = m_an4_func(); break;
case 5: cr = m_an5_func(); break; case 5: m_tmpcr = m_an5_func(); break;
case 6: cr = m_an6_func(); break; case 6: m_tmpcr = m_an6_func(); break;
case 7: cr = m_an7_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) switch (m_adout)
{ {
case 0: CR0 = cr; break; case 0: CR0 = m_tmpcr; break;
case 1: CR1 = cr; break; case 1: CR1 = m_tmpcr; break;
case 2: CR2 = cr; break; case 2: CR2 = m_tmpcr; break;
case 3: CR3 = cr; break; case 3: CR3 = m_tmpcr; break;
} }
m_adout = (m_adout + 1) & 0x07; m_adout = (m_adout + 1) & 0x03;
if (m_adout == 0) if (m_adout == 0)
IRR |= INTFAD; IRR |= INTFAD;
m_shdone = 0;
} }
} }
else else
{ {
/* scan mode */ /* scan mode */
while (m_adcnt > m_adtot) if (m_shdone == 0)
{ {
UINT8 cr = 0;
m_adcnt -= m_adtot;
switch (m_adin | m_adrange) switch (m_adin | m_adrange)
{ {
case 0: cr = m_an0_func(); break; case 0: m_tmpcr = m_an0_func(); break;
case 1: cr = m_an1_func(); break; case 1: m_tmpcr = m_an1_func(); break;
case 2: cr = m_an2_func(); break; case 2: m_tmpcr = m_an2_func(); break;
case 3: cr = m_an3_func(); break; case 3: m_tmpcr = m_an3_func(); break;
case 4: cr = m_an4_func(); break; case 4: m_tmpcr = m_an4_func(); break;
case 5: cr = m_an5_func(); break; case 5: m_tmpcr = m_an5_func(); break;
case 6: cr = m_an6_func(); break; case 6: m_tmpcr = m_an6_func(); break;
case 7: cr = m_an7_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) switch (m_adout)
{ {
case 0: CR0 = cr; break; case 0: CR0 = m_tmpcr; break;
case 1: CR1 = cr; break; case 1: CR1 = m_tmpcr; break;
case 2: CR2 = cr; break; case 2: CR2 = m_tmpcr; break;
case 3: CR3 = cr; break; case 3: CR3 = m_tmpcr; break;
} }
m_adin = (m_adin + 1) & 0x07; m_adin = (m_adin + 1) & 0x07;
m_adout = (m_adout + 1) & 0x07; m_adout = (m_adout + 1) & 0x03;
if (m_adout == 0) if (m_adout == 0)
IRR |= INTFAD; IRR |= INTFAD;
m_shdone = 0;
} }
} }
@ -1902,6 +1805,8 @@ void upd7810_device::device_reset()
m_edges = 0; m_edges = 0;
m_adcnt = 0; m_adcnt = 0;
m_adtot = 0; m_adtot = 0;
m_tmpcr = 0;
m_shdone = 0;
m_adout = 0; m_adout = 0;
m_adin = 0; m_adin = 0;
m_adrange = 0; m_adrange = 0;

View File

@ -169,17 +169,20 @@ protected:
virtual void handle_timers(int cycles); virtual void handle_timers(int cycles);
virtual void upd7810_take_irq(); 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_to_func;
devcb_write_line m_txd_func; devcb_write_line m_txd_func;
devcb_read_line m_rxd_func; devcb_read_line m_rxd_func;
devcb_read_line m_an0_func; devcb_read8 m_an0_func;
devcb_read_line m_an1_func; devcb_read8 m_an1_func;
devcb_read_line m_an2_func; devcb_read8 m_an2_func;
devcb_read_line m_an3_func; devcb_read8 m_an3_func;
devcb_read_line m_an4_func; devcb_read8 m_an4_func;
devcb_read_line m_an5_func; devcb_read8 m_an5_func;
devcb_read_line m_an6_func; devcb_read8 m_an6_func;
devcb_read_line m_an7_func; devcb_read8 m_an7_func;
typedef void (upd7810_device::*opcode_func)(); typedef void (upd7810_device::*opcode_func)();
@ -308,6 +311,8 @@ protected:
UINT8 m_edges; /* rising/falling edge flag for serial I/O */ UINT8 m_edges; /* rising/falling edge flag for serial I/O */
UINT16 m_adcnt; /* A/D converter cycle count */ UINT16 m_adcnt; /* A/D converter cycle count */
UINT8 m_adtot; /* A/D converter total cycles per conversion */ 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_adout; /* currently selected A/D converter output register */
int m_adin; /* currently selected A/D converter input */ int m_adin; /* currently selected A/D converter input */
int m_adrange;/* in scan mode, A/D converter range (AN0-AN3 or AN4-AN7) */ int m_adrange;/* in scan mode, A/D converter range (AN0-AN3 or AN4-AN7) */