mirror of
https://github.com/holub/mame
synced 2025-05-22 13:48:55 +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_CMOS = 0x02,
|
||||
FEATURE_I80C52 = 0x04,
|
||||
FEATURE_DS5002FP = 0x08,
|
||||
};
|
||||
|
||||
/* Internal address in SFR of registers */
|
||||
@ -159,8 +160,18 @@ enum
|
||||
ADDR_SADEN = 0xb9,
|
||||
|
||||
/* Philips 80C52 */
|
||||
AUXR = 0x8e,
|
||||
AUXR1 = 0xa2,
|
||||
ADDR_AUXR = 0x8e,
|
||||
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 */
|
||||
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 num_interrupts; /* number of interrupts supported */
|
||||
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 t1_cnt; /* number of 0->1 transistions on T1 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 *sfr_ram; /* 128 SFR - these are in 0x80 - 0xFF */
|
||||
|
||||
// SFR Callbacks
|
||||
/* SFR Callbacks */
|
||||
void (*sfr_write)(size_t offset, UINT8 data);
|
||||
UINT8 (*sfr_read)(size_t offset);
|
||||
|
||||
//Interrupt Callback
|
||||
/* Interrupt Callback */
|
||||
int (*irq_callback)(int irqline);
|
||||
|
||||
//Serial Port TX/RX Callbacks
|
||||
/* Serial Port TX/RX Callbacks */
|
||||
// TODO: Move to special port r/w
|
||||
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
|
||||
|
||||
/* 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)
|
||||
|
||||
/* 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 */
|
||||
|
||||
/* Shortcuts */
|
||||
@ -517,6 +551,36 @@ struct _mcs51_regs
|
||||
#define GET_CT2 GET_BIT(T2CON, 1)
|
||||
#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*/
|
||||
#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)
|
||||
@ -581,6 +645,7 @@ INLINE void clear_current_irq(void)
|
||||
mcs51.cur_irq_prio = 0;
|
||||
else
|
||||
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); }
|
||||
@ -900,28 +965,90 @@ 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)
|
||||
{
|
||||
int mode = (GET_M1_1<<1) | GET_M1_0;
|
||||
int mode_0 = (GET_M0_1<<1) | GET_M0_0;
|
||||
UINT8 mode = (GET_M1_1<<1) | GET_M1_0;
|
||||
UINT8 mode_0 = (GET_M0_1<<1) | GET_M0_0;
|
||||
UINT32 count = 0;
|
||||
|
||||
if (GET_TR1)
|
||||
if (mode_0 != 3)
|
||||
{
|
||||
if (GET_TR1)
|
||||
{
|
||||
UINT32 delta;
|
||||
UINT32 overflow = 0;
|
||||
|
||||
/* counter / external input */
|
||||
delta = GET_CT1 ? mcs51.t1_cnt : cycles;
|
||||
/* taken, reset */
|
||||
mcs51.t1_cnt = 0;
|
||||
/* TODO: Not sure about IE0. The manual specifies INT0=high,
|
||||
* which in turn means CLEAR_LINE. Change to access last_state?
|
||||
* IE0 may be edge triggered depending on IT0 */
|
||||
if (GET_GATE1 && !GET_IE1)
|
||||
delta = 0;
|
||||
|
||||
//printf("mode: %d\n", mode);
|
||||
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)
|
||||
{
|
||||
SET_TF1(1);
|
||||
transmit_receive(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
UINT32 delta;
|
||||
UINT32 overflow = 0;
|
||||
|
||||
/* counter / external input */
|
||||
delta = GET_CT1 ? mcs51.t1_cnt : cycles;
|
||||
|
||||
delta = cycles;
|
||||
/* taken, reset */
|
||||
mcs51.t1_cnt = 0;
|
||||
/* TODO: Not sure about IE0. The manual specifies INT0=high,
|
||||
* which in turn means CLEAR_LINE. Change to access last_state?
|
||||
* IE0 may be edge triggered depending on IT0 */
|
||||
if (GET_GATE1 && !GET_IE1)
|
||||
delta = 0;
|
||||
|
||||
//printf("mode: %d\n", mode);
|
||||
switch(mode) {
|
||||
case 0: /* 13 Bit Timer Mode */
|
||||
count = ((TH1<<5) | ( TL1 & 0x1f ) );
|
||||
@ -953,13 +1080,6 @@ INLINE void update_timer_t1(int cycles)
|
||||
}
|
||||
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);
|
||||
transmit_receive(1);
|
||||
}
|
||||
}
|
||||
@ -1487,18 +1607,30 @@ static void check_irqs(void)
|
||||
UINT8 ints = (GET_IE0 | (GET_TF0<<1) | (GET_IE1<<2) | (GET_TF1<<3)
|
||||
| ((GET_RI|GET_TI)<<4));
|
||||
UINT8 int_vec = 0;
|
||||
UINT8 int_mask = 0;
|
||||
int priority_request = -1;
|
||||
int i;
|
||||
|
||||
//If All Inerrupts Disabled or no pending abort..
|
||||
if(!GET_EA) return;
|
||||
int_mask = (GET_EA ? IE : 0x00);
|
||||
|
||||
if (mcs51.features & FEATURE_I8052)
|
||||
ints |= ((GET_TF2|GET_EXF2)<<5);
|
||||
|
||||
/* mask out interrupts not enabled */
|
||||
ints &= IE;
|
||||
|
||||
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 */
|
||||
ints &= ((int_mask & 0x1f) | ((GET_EPFW)<<5));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* mask out interrupts not enabled */
|
||||
ints &= int_mask;
|
||||
}
|
||||
|
||||
if (!ints) return;
|
||||
|
||||
/* CLear IDL - got enabled interrupt */
|
||||
@ -1508,7 +1640,9 @@ static void check_irqs(void)
|
||||
SET_IDL(0);
|
||||
/* external interrupt wakes up */
|
||||
if (ints & (GET_IE0 | GET_IE1))
|
||||
SET_PD(0);
|
||||
/* but not the DS5002FP */
|
||||
if (!(mcs51.features & FEATURE_DS5002FP))
|
||||
SET_PD(0);
|
||||
}
|
||||
|
||||
for (i=0; i<mcs51.num_interrupts; i++)
|
||||
@ -1527,7 +1661,8 @@ static void check_irqs(void)
|
||||
* 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"));
|
||||
return;
|
||||
@ -1545,6 +1680,8 @@ static void check_irqs(void)
|
||||
mcs51.cur_irq_prio = 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);
|
||||
|
||||
//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);
|
||||
break;
|
||||
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;
|
||||
/* I8052 specific */
|
||||
case V_TF2:
|
||||
// no flags are cleared according to manual
|
||||
/* no flags are cleared according to manual */
|
||||
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)
|
||||
*
|
||||
*/
|
||||
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 */
|
||||
int tr_state = (~mcs51.last_line_state) & new_state;
|
||||
UINT32 tr_state = (~mcs51.last_line_state) & new_state;
|
||||
|
||||
switch( irqline )
|
||||
{
|
||||
@ -1689,14 +1832,26 @@ static void mcs51_set_irq_line(int irqline, int state)
|
||||
else
|
||||
fatalerror("mcs51: Trying to set T2EX_LINE on a non I8052 type cpu.\n");
|
||||
break;
|
||||
//Serial Port Receive
|
||||
case MCS51_RX_LINE:
|
||||
//Is the enable flags for this interrupt set?
|
||||
|
||||
case MCS51_RX_LINE: /* Serial Port Receive */
|
||||
/* Is the enable flags for this interrupt set? */
|
||||
if (state != CLEAR_LINE)
|
||||
{
|
||||
serial_receive();
|
||||
}
|
||||
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;
|
||||
}
|
||||
@ -1746,8 +1901,21 @@ static int mcs51_execute(int cycles)
|
||||
|
||||
/* burn the 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);
|
||||
|
||||
/* 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 );
|
||||
|
||||
return cycles - mcs51_icount;
|
||||
@ -1933,6 +2101,25 @@ static void mcs51_reset(void)
|
||||
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 */
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* 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
|
||||
|
@ -58,6 +58,8 @@ enum
|
||||
MCS51_T1_LINE, /* P3.5: Timer 1 External Input */
|
||||
MCS51_T2_LINE, /* P1.0: Timer 2 External Input */
|
||||
MCS51_T2EX_LINE, /* P1.1: Timer 2 Capture Reload Trigger */
|
||||
|
||||
DS5002FP_PFI_LINE, /* DS5002FP Power fail interrupt */
|
||||
};
|
||||
|
||||
/* special I/O space ports */
|
||||
@ -71,6 +73,18 @@ enum
|
||||
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
|
||||
|
Loading…
Reference in New Issue
Block a user