mirror of
https://github.com/holub/mame
synced 2025-05-23 06:08:48 +03:00
More changes to timer 0 split mode 3 and how timer 1 operates than
* Quotes from the documentation added to the source as well * Started DS5002FP integration
This commit is contained in:
parent
4791a80745
commit
10b85f1efe
@ -118,6 +118,7 @@ enum
|
|||||||
FEATURE_I8052 = 0x01,
|
FEATURE_I8052 = 0x01,
|
||||||
FEATURE_CMOS = 0x02,
|
FEATURE_CMOS = 0x02,
|
||||||
FEATURE_I80C52 = 0x04,
|
FEATURE_I80C52 = 0x04,
|
||||||
|
FEATURE_DS5002FP = 0x08,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Internal address in SFR of registers */
|
/* Internal address in SFR of registers */
|
||||||
@ -159,8 +160,18 @@ enum
|
|||||||
ADDR_SADEN = 0xb9,
|
ADDR_SADEN = 0xb9,
|
||||||
|
|
||||||
/* Philips 80C52 */
|
/* Philips 80C52 */
|
||||||
AUXR = 0x8e,
|
ADDR_AUXR = 0x8e,
|
||||||
AUXR1 = 0xa2,
|
ADDR_AUXR1 = 0xa2,
|
||||||
|
|
||||||
|
/* DS5002FP */
|
||||||
|
ADDR_CRCR = 0xc1,
|
||||||
|
ADDR_CRCL = 0xc2,
|
||||||
|
ADDR_CRCH = 0xc3,
|
||||||
|
ADDR_MCON = 0xc6,
|
||||||
|
ADDR_TA = 0xc7,
|
||||||
|
ADDR_RNR = 0xcf,
|
||||||
|
ADDR_RPCTL = 0xd8,
|
||||||
|
ADDR_RPS = 0xda,
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -177,6 +188,9 @@ enum
|
|||||||
|
|
||||||
/* 8052 Only Vectors */
|
/* 8052 Only Vectors */
|
||||||
V_TF2 = 0x02b, /* Timer 2 Overflow */
|
V_TF2 = 0x02b, /* Timer 2 Overflow */
|
||||||
|
|
||||||
|
/* DS5002FP */
|
||||||
|
V_PFI = 0x02b, /* Power Failure Interrupt */
|
||||||
};
|
};
|
||||||
|
|
||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
@ -208,7 +222,7 @@ struct _mcs51_regs
|
|||||||
int ram_mask; /* second ram bank for indirect access available ? */
|
int ram_mask; /* second ram bank for indirect access available ? */
|
||||||
int num_interrupts; /* number of interrupts supported */
|
int num_interrupts; /* number of interrupts supported */
|
||||||
int recalc_parity; /* recalculate parity before next instruction */
|
int recalc_parity; /* recalculate parity before next instruction */
|
||||||
int last_line_state; /* last state of input lines line */
|
UINT32 last_line_state; /* last state of input lines line */
|
||||||
int t0_cnt; /* number of 0->1 transistions on T0 line */
|
int t0_cnt; /* number of 0->1 transistions on T0 line */
|
||||||
int t1_cnt; /* number of 0->1 transistions on T1 line */
|
int t1_cnt; /* number of 0->1 transistions on T1 line */
|
||||||
int t2_cnt; /* number of 0->1 transistions on T2 line */
|
int t2_cnt; /* number of 0->1 transistions on T2 line */
|
||||||
@ -223,18 +237,27 @@ struct _mcs51_regs
|
|||||||
UINT8 *internal_ram; /* 128 RAM (8031/51) + 128 RAM in second bank (8032/52) */
|
UINT8 *internal_ram; /* 128 RAM (8031/51) + 128 RAM in second bank (8032/52) */
|
||||||
UINT8 *sfr_ram; /* 128 SFR - these are in 0x80 - 0xFF */
|
UINT8 *sfr_ram; /* 128 SFR - these are in 0x80 - 0xFF */
|
||||||
|
|
||||||
// SFR Callbacks
|
/* SFR Callbacks */
|
||||||
void (*sfr_write)(size_t offset, UINT8 data);
|
void (*sfr_write)(size_t offset, UINT8 data);
|
||||||
UINT8 (*sfr_read)(size_t offset);
|
UINT8 (*sfr_read)(size_t offset);
|
||||||
|
|
||||||
//Interrupt Callback
|
/* Interrupt Callback */
|
||||||
int (*irq_callback)(int irqline);
|
int (*irq_callback)(int irqline);
|
||||||
|
|
||||||
//Serial Port TX/RX Callbacks
|
/* Serial Port TX/RX Callbacks */
|
||||||
// TODO: Move to special port r/w
|
// TODO: Move to special port r/w
|
||||||
void (*serial_tx_callback)(int data); //Call back funciton when sending data out of serial port
|
void (*serial_tx_callback)(int data); //Call back funciton when sending data out of serial port
|
||||||
int (*serial_rx_callback)(void); //Call back function to retrieve data when receiving serial port data
|
int (*serial_rx_callback)(void); //Call back function to retrieve data when receiving serial port data
|
||||||
|
|
||||||
|
/* DS5002FP */
|
||||||
|
struct {
|
||||||
|
UINT8 previous_ta; /* Previous Timed Access value */
|
||||||
|
UINT8 ta_window; /* Limed Access window */
|
||||||
|
UINT8 range; /* Memory Range */
|
||||||
|
const ds5002fp_config *config; /* Bootstrap Configuration */
|
||||||
|
} ds5002fp;
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
@ -349,6 +372,17 @@ struct _mcs51_regs
|
|||||||
*/
|
*/
|
||||||
#define AUXR1 SFR_A(ADDR_AUXR1)
|
#define AUXR1 SFR_A(ADDR_AUXR1)
|
||||||
|
|
||||||
|
/* DS5002FP only registers */
|
||||||
|
#define CRCR SFR_A(ADDR_CRCR)
|
||||||
|
#define CRCL SFR_A(ADDR_CRCL)
|
||||||
|
#define CRCH SFR_A(ADDR_CRCH)
|
||||||
|
#define MCON SFR_A(ADDR_MCON)
|
||||||
|
#define TA SFR_A(ADDR_TA)
|
||||||
|
#define RNR SFR_A(ADDR_RNR)
|
||||||
|
#define RPCTL SFR_A(ADDR_RPCTL)
|
||||||
|
#define RPS SFR_A(ADDR_RPS)
|
||||||
|
|
||||||
|
|
||||||
/* WRITE accessors */
|
/* WRITE accessors */
|
||||||
|
|
||||||
/* Shortcuts */
|
/* Shortcuts */
|
||||||
@ -517,6 +551,36 @@ struct _mcs51_regs
|
|||||||
#define GET_CT2 GET_BIT(T2CON, 1)
|
#define GET_CT2 GET_BIT(T2CON, 1)
|
||||||
#define GET_CP GET_BIT(T2CON, 0)
|
#define GET_CP GET_BIT(T2CON, 0)
|
||||||
|
|
||||||
|
/* DS5002FP Only flags */
|
||||||
|
|
||||||
|
/* PCON Flags - DS5002FP */
|
||||||
|
|
||||||
|
#define GET_POR GET_BIT(PCON, 6)
|
||||||
|
#define GET_PFW GET_BIT(PCON, 5)
|
||||||
|
#define GET_WTR GET_BIT(PCON, 4)
|
||||||
|
#define GET_EPFW GET_BIT(PCON, 3)
|
||||||
|
#define GET_EWT GET_BIT(PCON, 2)
|
||||||
|
|
||||||
|
#define SET_PFW(n) SET_BIT(PCON, 5, n)
|
||||||
|
|
||||||
|
/* MCON Flags - DS5002FP */
|
||||||
|
|
||||||
|
#define GET_PA ((MCON & 0xf0)>>4)
|
||||||
|
#define GET_RG1 GET_BIT(MCON, 3)
|
||||||
|
#define GET_PES GET_BIT(MCON, 2)
|
||||||
|
#define GET_PM GET_BIT(MCON, 1)
|
||||||
|
#define GET_SL GET_BIT(MCON, 0)
|
||||||
|
|
||||||
|
/* RPCTL Flags - DS5002FP */
|
||||||
|
#define GET_RNR GET_BIT(RPCTL, 7) /* Bit 6 ?? */
|
||||||
|
#define GET_EXBS GET_BIT(RPCTL, 5)
|
||||||
|
#define GET_AE GET_BIT(RPCTL, 4)
|
||||||
|
#define GET_IBI GET_BIT(RPCTL, 3)
|
||||||
|
#define GET_DMA GET_BIT(RPCTL, 2)
|
||||||
|
#define GET_RPCON GET_BIT(RPCTL, 1)
|
||||||
|
#define GET_RG0 GET_BIT(RPCTL, 0)
|
||||||
|
|
||||||
|
|
||||||
/*Add and Subtract Flag settings*/
|
/*Add and Subtract Flag settings*/
|
||||||
#define DO_ADD_FLAGS(a,d,c) do_add_flags(a,d,c)
|
#define DO_ADD_FLAGS(a,d,c) do_add_flags(a,d,c)
|
||||||
#define DO_SUB_FLAGS(a,d,c) do_sub_flags(a,d,c)
|
#define DO_SUB_FLAGS(a,d,c) do_sub_flags(a,d,c)
|
||||||
@ -581,6 +645,7 @@ INLINE void clear_current_irq(void)
|
|||||||
mcs51.cur_irq_prio = 0;
|
mcs51.cur_irq_prio = 0;
|
||||||
else
|
else
|
||||||
mcs51.cur_irq_prio = -1;
|
mcs51.cur_irq_prio = -1;
|
||||||
|
LOG(("New: %d %02x\n", mcs51.cur_irq_prio, mcs51.irq_active));
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE UINT8 r_acc(void) { return SFR_A(ADDR_ACC); }
|
INLINE UINT8 r_acc(void) { return SFR_A(ADDR_ACC); }
|
||||||
@ -900,12 +965,30 @@ INLINE void update_timer_t0(int cycles)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* From the DS5002FP User Manual
|
||||||
|
When Timer 1 is selected for operation in Mode 3, it stops counting and holds its current value. This
|
||||||
|
action is the same as setting TR1 = 0. When Timer 0 is selected in Mode 3, Timer 1’s control bits are
|
||||||
|
stolen as described above. As a result, Timer 1’s functions are limited in this MODE. It is forced to
|
||||||
|
operate as a timer whose clock in-put is 12 tCLK and it cannot generate an interrupt on overflow. In
|
||||||
|
addition, it also cannot be used with the GATE function. However, it can be started and stopped by
|
||||||
|
switching it into or out of Mode 3 or it can be assigned as a baud rate generator for the serial port.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Intel documentation:
|
||||||
|
* Timer 1 may still be used in modes 0, 1, and 2, while timer 0
|
||||||
|
* is in mode 3. With one important exception: No interrupts
|
||||||
|
* will be generated by timer 1 while timer 0 is using the TF1
|
||||||
|
* overflow flag
|
||||||
|
*/
|
||||||
|
|
||||||
INLINE void update_timer_t1(int cycles)
|
INLINE void update_timer_t1(int cycles)
|
||||||
{
|
{
|
||||||
int mode = (GET_M1_1<<1) | GET_M1_0;
|
UINT8 mode = (GET_M1_1<<1) | GET_M1_0;
|
||||||
int mode_0 = (GET_M0_1<<1) | GET_M0_0;
|
UINT8 mode_0 = (GET_M0_1<<1) | GET_M0_0;
|
||||||
UINT32 count = 0;
|
UINT32 count = 0;
|
||||||
|
|
||||||
|
if (mode_0 != 3)
|
||||||
|
{
|
||||||
if (GET_TR1)
|
if (GET_TR1)
|
||||||
{
|
{
|
||||||
UINT32 delta;
|
UINT32 delta;
|
||||||
@ -953,16 +1036,53 @@ INLINE void update_timer_t1(int cycles)
|
|||||||
}
|
}
|
||||||
if (overflow)
|
if (overflow)
|
||||||
{
|
{
|
||||||
/* Timer 1 may still be used in modes 0, 1, and 2, while timer 0
|
|
||||||
* is in mode 3. With one important exception: No interrupts
|
|
||||||
* will be generated by timer 1 while timer 0 is using the TF1
|
|
||||||
* overflow flag
|
|
||||||
*/
|
|
||||||
if (mode_0 != 3)
|
|
||||||
SET_TF1(1);
|
SET_TF1(1);
|
||||||
transmit_receive(1);
|
transmit_receive(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UINT32 delta;
|
||||||
|
UINT32 overflow = 0;
|
||||||
|
|
||||||
|
delta = cycles;
|
||||||
|
/* taken, reset */
|
||||||
|
mcs51.t1_cnt = 0;
|
||||||
|
switch(mode) {
|
||||||
|
case 0: /* 13 Bit Timer Mode */
|
||||||
|
count = ((TH1<<5) | ( TL1 & 0x1f ) );
|
||||||
|
count += delta;
|
||||||
|
overflow = count & 0xffffe000; /* Check for overflow */
|
||||||
|
TH1 = (count>>5) & 0xff;
|
||||||
|
TL1 = count & 0x1f ;
|
||||||
|
break;
|
||||||
|
case 1: /* 16 Bit Timer Mode */
|
||||||
|
count = ((TH1<<8) | TL1);
|
||||||
|
count += delta;
|
||||||
|
overflow = count & 0xffff0000; /* Check for overflow */
|
||||||
|
TH1 = (count>>8) & 0xff;
|
||||||
|
TL1 = count & 0xff;
|
||||||
|
break;
|
||||||
|
case 2: /* 8 Bit Autoreload */
|
||||||
|
count = ((UINT32) TL1) + delta;
|
||||||
|
overflow = count & 0xffffff00; /* Check for overflow */
|
||||||
|
if ( overflow )
|
||||||
|
{
|
||||||
|
count += TH1; /* Reload timer */
|
||||||
|
}
|
||||||
|
/* Update new values of the counter */
|
||||||
|
TL1 = count & 0xff;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
/* do nothing */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (overflow)
|
||||||
|
{
|
||||||
|
transmit_receive(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE void update_timer_t2(int cycles)
|
INLINE void update_timer_t2(int cycles)
|
||||||
@ -1487,17 +1607,29 @@ static void check_irqs(void)
|
|||||||
UINT8 ints = (GET_IE0 | (GET_TF0<<1) | (GET_IE1<<2) | (GET_TF1<<3)
|
UINT8 ints = (GET_IE0 | (GET_TF0<<1) | (GET_IE1<<2) | (GET_TF1<<3)
|
||||||
| ((GET_RI|GET_TI)<<4));
|
| ((GET_RI|GET_TI)<<4));
|
||||||
UINT8 int_vec = 0;
|
UINT8 int_vec = 0;
|
||||||
|
UINT8 int_mask = 0;
|
||||||
int priority_request = -1;
|
int priority_request = -1;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
//If All Inerrupts Disabled or no pending abort..
|
//If All Inerrupts Disabled or no pending abort..
|
||||||
if(!GET_EA) return;
|
int_mask = (GET_EA ? IE : 0x00);
|
||||||
|
|
||||||
if (mcs51.features & FEATURE_I8052)
|
if (mcs51.features & FEATURE_I8052)
|
||||||
ints |= ((GET_TF2|GET_EXF2)<<5);
|
ints |= ((GET_TF2|GET_EXF2)<<5);
|
||||||
|
|
||||||
|
if (mcs51.features & FEATURE_DS5002FP)
|
||||||
|
{
|
||||||
|
printf("Here\n");
|
||||||
|
ints |= ((GET_PFW)<<5);
|
||||||
|
mcs51.irq_prio[6] = 3; /* force highest priority */
|
||||||
/* mask out interrupts not enabled */
|
/* mask out interrupts not enabled */
|
||||||
ints &= IE;
|
ints &= ((int_mask & 0x1f) | ((GET_EPFW)<<5));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* mask out interrupts not enabled */
|
||||||
|
ints &= int_mask;
|
||||||
|
}
|
||||||
|
|
||||||
if (!ints) return;
|
if (!ints) return;
|
||||||
|
|
||||||
@ -1508,6 +1640,8 @@ static void check_irqs(void)
|
|||||||
SET_IDL(0);
|
SET_IDL(0);
|
||||||
/* external interrupt wakes up */
|
/* external interrupt wakes up */
|
||||||
if (ints & (GET_IE0 | GET_IE1))
|
if (ints & (GET_IE0 | GET_IE1))
|
||||||
|
/* but not the DS5002FP */
|
||||||
|
if (!(mcs51.features & FEATURE_DS5002FP))
|
||||||
SET_PD(0);
|
SET_PD(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1527,7 +1661,8 @@ static void check_irqs(void)
|
|||||||
* and the new request does not have a higher priority
|
* and the new request does not have a higher priority
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if(mcs51.irq_active && (priority_request <= mcs51.cur_irq_prio))
|
LOG(("Request: %d\n", priority_request));
|
||||||
|
if (mcs51.irq_active && (priority_request <= mcs51.cur_irq_prio))
|
||||||
{
|
{
|
||||||
LOG(("higher or equal priority irq in progress already, skipping ...\n"));
|
LOG(("higher or equal priority irq in progress already, skipping ...\n"));
|
||||||
return;
|
return;
|
||||||
@ -1545,6 +1680,8 @@ static void check_irqs(void)
|
|||||||
mcs51.cur_irq_prio = priority_request;
|
mcs51.cur_irq_prio = priority_request;
|
||||||
mcs51.irq_active |= (1 << priority_request);
|
mcs51.irq_active |= (1 << priority_request);
|
||||||
|
|
||||||
|
LOG(("Take: %d %02x\n", mcs51.cur_irq_prio, mcs51.irq_active));
|
||||||
|
|
||||||
//printf("irq cip %d, act %02x\n",mcs51.cur_irq_prio, mcs51.irq_active);
|
//printf("irq cip %d, act %02x\n",mcs51.cur_irq_prio, mcs51.irq_active);
|
||||||
|
|
||||||
//Clear any interrupt flags that should be cleared since we're servicing the irq!
|
//Clear any interrupt flags that should be cleared since we're servicing the irq!
|
||||||
@ -1577,12 +1714,18 @@ static void check_irqs(void)
|
|||||||
SET_TF1(0);
|
SET_TF1(0);
|
||||||
break;
|
break;
|
||||||
case V_RITI:
|
case V_RITI:
|
||||||
// no flags are cleared, TI and RI remain set until reset by software
|
/* no flags are cleared, TI and RI remain set until reset by software */
|
||||||
break;
|
break;
|
||||||
/* I8052 specific */
|
/* I8052 specific */
|
||||||
case V_TF2:
|
case V_TF2:
|
||||||
// no flags are cleared according to manual
|
/* no flags are cleared according to manual */
|
||||||
break;
|
break;
|
||||||
|
/* DS5002FP specific */
|
||||||
|
/* case V_PFI:
|
||||||
|
* no flags are cleared, PFW is reset by software
|
||||||
|
* This has the same vector as V_TF2.
|
||||||
|
*/
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1611,9 +1754,9 @@ static void mcs51_set_irq_line(int irqline, int state)
|
|||||||
* for at least one cycle (12 states)
|
* for at least one cycle (12 states)
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
int new_state = (mcs51.last_line_state & ~(1 << irqline)) | ((state != CLEAR_LINE) << irqline);
|
UINT32 new_state = (mcs51.last_line_state & ~(1 << irqline)) | ((state != CLEAR_LINE) << irqline);
|
||||||
/* detect 0->1 transistions */
|
/* detect 0->1 transistions */
|
||||||
int tr_state = (~mcs51.last_line_state) & new_state;
|
UINT32 tr_state = (~mcs51.last_line_state) & new_state;
|
||||||
|
|
||||||
switch( irqline )
|
switch( irqline )
|
||||||
{
|
{
|
||||||
@ -1689,14 +1832,26 @@ static void mcs51_set_irq_line(int irqline, int state)
|
|||||||
else
|
else
|
||||||
fatalerror("mcs51: Trying to set T2EX_LINE on a non I8052 type cpu.\n");
|
fatalerror("mcs51: Trying to set T2EX_LINE on a non I8052 type cpu.\n");
|
||||||
break;
|
break;
|
||||||
//Serial Port Receive
|
|
||||||
case MCS51_RX_LINE:
|
case MCS51_RX_LINE: /* Serial Port Receive */
|
||||||
//Is the enable flags for this interrupt set?
|
/* Is the enable flags for this interrupt set? */
|
||||||
if (state != CLEAR_LINE)
|
if (state != CLEAR_LINE)
|
||||||
{
|
{
|
||||||
serial_receive();
|
serial_receive();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
/* Power Fail Interrupt */
|
||||||
|
case DS5002FP_PFI_LINE:
|
||||||
|
if (mcs51.features & FEATURE_DS5002FP)
|
||||||
|
{
|
||||||
|
/* Need cleared->active line transition? (Logical 1-0 Pulse on the line) - CLEAR->ASSERT Transition since INT1 active lo! */
|
||||||
|
if (GET_BIT(tr_state, MCS51_INT1_LINE))
|
||||||
|
SET_PFW(1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
fatalerror("mcs51: Trying to set DS5002FP_PFI_LINE on a non DS5002FP type cpu.\n");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
mcs51.last_line_state = new_state;
|
mcs51.last_line_state = new_state;
|
||||||
}
|
}
|
||||||
@ -1746,8 +1901,21 @@ static int mcs51_execute(int cycles)
|
|||||||
|
|
||||||
/* burn the cycles */
|
/* burn the cycles */
|
||||||
mcs51_icount -= mcs51.inst_cycles;
|
mcs51_icount -= mcs51.inst_cycles;
|
||||||
|
|
||||||
|
/* if in powerdown, just return */
|
||||||
|
if ((mcs51.features & FEATURE_CMOS) && GET_PD)
|
||||||
|
return cycles - mcs51_icount;
|
||||||
|
|
||||||
burn_cycles(mcs51.inst_cycles);
|
burn_cycles(mcs51.inst_cycles);
|
||||||
|
|
||||||
|
/* decrement the timed access window */
|
||||||
|
if (mcs51.features & FEATURE_DS5002FP)
|
||||||
|
mcs51.ds5002fp.ta_window = (mcs51.ds5002fp.ta_window ? mcs51.ds5002fp.ta_window-- : 0x00);
|
||||||
|
|
||||||
|
/* If the chip entered in idle mode, end the loop */
|
||||||
|
if ((mcs51.features & FEATURE_CMOS) && GET_IDL)
|
||||||
|
return cycles - mcs51_icount;
|
||||||
|
|
||||||
} while( mcs51_icount > 0 );
|
} while( mcs51_icount > 0 );
|
||||||
|
|
||||||
return cycles - mcs51_icount;
|
return cycles - mcs51_icount;
|
||||||
@ -1933,6 +2101,25 @@ static void mcs51_reset(void)
|
|||||||
SADEN = 0;
|
SADEN = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* DS5002FP Only registers */
|
||||||
|
if (mcs51.features & FEATURE_DS5002FP)
|
||||||
|
{
|
||||||
|
// set initial values (some of them are set using the bootstrap loader)
|
||||||
|
PCON = 0;
|
||||||
|
MCON = mcs51.ds5002fp.config->mcon & 0xfb;
|
||||||
|
RPCTL = mcs51.ds5002fp.config->rpctl & 0x01;
|
||||||
|
RPS = 0;
|
||||||
|
RNR = 0;
|
||||||
|
CRCR = mcs51.ds5002fp.config->crc & 0xf0;
|
||||||
|
CRCL = 0;
|
||||||
|
CRCH = 0;
|
||||||
|
TA = 0;
|
||||||
|
|
||||||
|
// set internal CPU state
|
||||||
|
mcs51.ds5002fp.previous_ta = 0;
|
||||||
|
mcs51.ds5002fp.ta_window = 0;
|
||||||
|
mcs51.ds5002fp.range = (GET_RG1 << 1) | GET_RG0;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2048,6 +2235,97 @@ static void i80c31_init(int index, int clock, const void *config, int (*irqcallb
|
|||||||
mcs51.ram_mask = 0x7F; /* 128 bytes of ram */
|
mcs51.ram_mask = 0x7F; /* 128 bytes of ram */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* DS5002FP Section
|
||||||
|
****************************************************************************/
|
||||||
|
#if 0
|
||||||
|
|
||||||
|
#define DS5_LOGW(a, d) LOG(("ds5002fp #%d: write to " # a " register at 0x%04x, data=%x\n", cpu_getactivecpu(), PC, d))
|
||||||
|
#define DS5_LOGR(a, d) LOG(("ds5002fp #%d: read from " # a " register at 0x%04x\n", cpu_getactivecpu(), PC))
|
||||||
|
|
||||||
|
INLINE UINT8 ds5002fp_protected(size_t offset, UINT8 data, UINT8 ta_mask, UINT8 mask)
|
||||||
|
{
|
||||||
|
UINT8 is_timed_access;
|
||||||
|
|
||||||
|
is_timed_access = (mcs51.ds5002fp.ta_window > 0) && (TA == 0x55);
|
||||||
|
if (is_timed_access)
|
||||||
|
{
|
||||||
|
ta_mask = 0xff;
|
||||||
|
}
|
||||||
|
data = (mcs51.sfr_ram[offset] & (~ta_mask)) | (data & ta_mask);
|
||||||
|
return (mcs51.sfr_ram[offset] & (~mask)) | (data & mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ds5002fp_sfr_write(size_t offset, UINT8 data)
|
||||||
|
{
|
||||||
|
switch (offset)
|
||||||
|
{
|
||||||
|
|
||||||
|
case ADDR_TA:
|
||||||
|
mcs51.ds5002fp.previous_ta = TA;
|
||||||
|
/* init the time window after having wrote 0xaa */
|
||||||
|
if ((data == 0xaa) && (mcs51.ds5002fp.ta_window == 0))
|
||||||
|
{
|
||||||
|
mcs51.ds5002fp.ta_window = 6; /* 4*12 + 2*12 */
|
||||||
|
LOG(("ds5002fp #%d: TA window initiated at 0x%04x\n", cpu_getactivecpu(), PC));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ADDR_MCON: data = ds5002fp_protected(ADDR_MCON, data, 0x0f, 0xf7); DS5_LOGW(MCON, data); break;
|
||||||
|
case ADDR_RPCTL: data = ds5002fp_protected(ADDR_RPCTL, data, 0xef, 0xfe); DS5_LOGW(RPCTL, data); break;
|
||||||
|
case ADDR_CRCR: data = ds5002fp_protected(ADDR_CRCR, data, 0xff, 0x0f); DS5_LOGW(CRCR, data); break;
|
||||||
|
case ADDR_PCON: data = ds5002fp_protected(ADDR_PCON, data, 0xb9, 0xff); break;
|
||||||
|
case ADDR_IP: data = ds5002fp_protected(ADDR_IP, data, 0x7f, 0xff); break;
|
||||||
|
case ADDR_CRCL: DS5_LOGW(CRCL, data); break;
|
||||||
|
case ADDR_CRCH: DS5_LOGW(CRCH, data); break;
|
||||||
|
case ADDR_RNR: DS5_LOGW(RNR, data); break;
|
||||||
|
case ADDR_RPS: DS5_LOGW(RPS, data); break;
|
||||||
|
default:
|
||||||
|
mcs51_sfr_write(offset, data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
data_write_byte_8le((size_t) offset | 0x100, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static UINT8 ds5002fp_sfr_read(size_t offset)
|
||||||
|
{
|
||||||
|
switch (offset)
|
||||||
|
{
|
||||||
|
case ADDR_CRCR: DS5_LOGR(CRCR, data); break;
|
||||||
|
case ADDR_CRCL: DS5_LOGR(CRCL, data); break;
|
||||||
|
case ADDR_CRCH: DS5_LOGR(CRCH, data); break;
|
||||||
|
case ADDR_MCON: DS5_LOGR(MCON, data); break;
|
||||||
|
case ADDR_TA: DS5_LOGR(TA, data); break;
|
||||||
|
case ADDR_RNR: DS5_LOGR(RNR, data); break;
|
||||||
|
case ADDR_RPCTL: DS5_LOGR(RPCTL, data); break;
|
||||||
|
case ADDR_RPS: DS5_LOGR(RPS, data); break;
|
||||||
|
case ADDR_PCON:
|
||||||
|
SET_PFW(0); /* reset PFW flag */
|
||||||
|
return mcs51_sfr_read(offset); /* FIXME: cmos features ??? */
|
||||||
|
default:
|
||||||
|
return mcs51_sfr_read(offset); /* FIXME: cmos features ??? */
|
||||||
|
}
|
||||||
|
return data_read_byte_8le((size_t) offset | 0x100);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ds5002fp_init(int index, int clock, const void *config, int (*irqcallback)(int))
|
||||||
|
{
|
||||||
|
/* default configuration */
|
||||||
|
static const ds5002fp_config default_config = { 0x00, 0x00, 0x00 };
|
||||||
|
const ds5002fp_config *sconfig = config ? config : &default_config;
|
||||||
|
|
||||||
|
mcs51_init(index, clock, config, irqcallback);
|
||||||
|
|
||||||
|
mcs51.ds5002fp.config = sconfig;
|
||||||
|
mcs51.features |= (FEATURE_DS5002FP | FEATURE_CMOS);
|
||||||
|
mcs51.sfr_read = ds5002fp_sfr_read;
|
||||||
|
mcs51.sfr_write = ds5002fp_sfr_write;
|
||||||
|
|
||||||
|
state_save_register_item("mcs51", index, mcs51.ds5002fp.previous_ta );
|
||||||
|
state_save_register_item("mcs51", index, mcs51.ds5002fp.ta_window );
|
||||||
|
state_save_register_item("mcs51", index, mcs51.ds5002fp.range );
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
ADDRESS MAPS
|
ADDRESS MAPS
|
||||||
|
@ -58,6 +58,8 @@ enum
|
|||||||
MCS51_T1_LINE, /* P3.5: Timer 1 External Input */
|
MCS51_T1_LINE, /* P3.5: Timer 1 External Input */
|
||||||
MCS51_T2_LINE, /* P1.0: Timer 2 External Input */
|
MCS51_T2_LINE, /* P1.0: Timer 2 External Input */
|
||||||
MCS51_T2EX_LINE, /* P1.1: Timer 2 Capture Reload Trigger */
|
MCS51_T2EX_LINE, /* P1.1: Timer 2 Capture Reload Trigger */
|
||||||
|
|
||||||
|
DS5002FP_PFI_LINE, /* DS5002FP Power fail interrupt */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* special I/O space ports */
|
/* special I/O space ports */
|
||||||
@ -71,6 +73,18 @@ enum
|
|||||||
MCS51_PORT_TX = 0x10004, /* P3.1 */
|
MCS51_PORT_TX = 0x10004, /* P3.1 */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
CONFIGURATION
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
/* configuration of the DS5002FP */
|
||||||
|
typedef struct _ds5002fp_config ds5002fp_config;
|
||||||
|
struct _ds5002fp_config
|
||||||
|
{
|
||||||
|
UINT8 mcon; /* bootstrap loader MCON register */
|
||||||
|
UINT8 rpctl; /* bootstrap loader RPCTL register */
|
||||||
|
UINT8 crc; /* bootstrap loader CRC register */
|
||||||
|
};
|
||||||
|
|
||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
FUNCTION PROTOTYPES
|
FUNCTION PROTOTYPES
|
||||||
|
Loading…
Reference in New Issue
Block a user