diff options
Diffstat (limited to 'trunk/src/emu/cpu/h83002/h8speriph.c')
-rw-r--r-- | trunk/src/emu/cpu/h83002/h8speriph.c | 1540 |
1 files changed, 1540 insertions, 0 deletions
diff --git a/trunk/src/emu/cpu/h83002/h8speriph.c b/trunk/src/emu/cpu/h83002/h8speriph.c new file mode 100644 index 00000000000..458a040b4d1 --- /dev/null +++ b/trunk/src/emu/cpu/h83002/h8speriph.c @@ -0,0 +1,1540 @@ +/* + + Hitachi H8S/2xxx MCU peripherals + + (c) 2001-2007 Tim Schuerewegen + + H8S/2241 + H8S/2246 + H8S/2323 + +*/ + +#include "emu.h" +#include "debugger.h" +#include "h8.h" +#include "h8priv.h" + +#define VERBOSE_LEVEL ( 0 ) + +INLINE void ATTR_PRINTF(3,4) verboselog( running_machine &machine, int n_level, const char *s_fmt, ...) +{ + if (VERBOSE_LEVEL >= n_level) + { + va_list v; + char buf[32768]; + va_start( v, s_fmt); + vsprintf( buf, s_fmt, v); + va_end( v); + logerror( "%s: %s", machine.describe_context( ), buf); + } +} + +const UINT8 H8S_RESET_H8S_IO_224x[0x1C0] = // values from "e602100_h8s2245.pdf" +{ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // FE40 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // FE50 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // FE60 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // FE70 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // FE80 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // FE90 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // FEA0 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, // FEB0 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // FEC0 + 0xFF, 0xFF, 0xFF, 0xFF, 0xD0, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // FED0 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // FEE0 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // FEF0 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // FF00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // FF10 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // FF20 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x01, 0x00, 0x00, 0x3F, 0xFF, 0x00, 0x00, // FF30 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // FF40 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // FF50 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // FF60 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x84, 0x00, 0xF2, 0x00, // FF70 + 0x00, 0xFF, 0x00, 0xFF, 0x84, 0x00, 0xF2, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x84, 0x00, 0xF2, 0x00, // FF80 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // FF90 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // FFA0 + 0x00, 0x00, 0x00, 0x10, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // FFB0 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // FFC0 + 0x00, 0xC0, 0x00, 0x00, 0x40, 0xC0, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // FFD0 + 0x00, 0xC0, 0x00, 0x00, 0x40, 0xC0, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, // FFE0 + 0x00, 0xC0, 0x00, 0x00, 0x40, 0xC0, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, // FFF0 +}; + +const UINT8 H8S_RESET_H8S_IO_2323[0x1C0] = // values from "rej09b0220_h8s2329.pdf" +{ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // FE40 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // FE50 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // FE60 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // FE70 + 0x00, 0xC0, 0x00, 0x00, 0x40, 0xC0, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // FE80 + 0x00, 0xC0, 0x00, 0x00, 0x40, 0xC0, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, // FE90 + 0x00, 0xC0, 0x00, 0x00, 0x40, 0xC0, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, // FEA0 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, // FEB0 + 0x00, 0x00, 0x00, 0x00, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x00, // FEC0 + 0xFF, 0xFF, 0xFF, 0xFF, 0xD0, 0x3C, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // FED0 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // FEE0 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // FEF0 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // FF00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // FF10 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // FF20 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x01, 0x00, 0x00, 0x3F, 0xFF, 0x00, 0x00, // FF30 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // FF40 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // FF50 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // FF60 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x84, 0x00, 0xF2, 0x00, // FF70 + 0x00, 0xFF, 0x00, 0xFF, 0x84, 0x00, 0xF2, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x84, 0x00, 0xF2, 0x00, // FF80 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // FF90 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, // FFA0 + 0x00, 0x00, 0x00, 0x10, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // FFB0 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // FFC0 + 0x00, 0xC0, 0x00, 0x00, 0x40, 0xC0, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // FFD0 + 0x00, 0xC0, 0x00, 0x00, 0x40, 0xC0, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, // FFE0 + 0x00, 0xC0, 0x00, 0x00, 0x40, 0xC0, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, // FFF0 +}; + +#define SCR_TIE 0x80 +#define SCR_RIE 0x40 +#define SCR_TE 0x20 +#define SCR_RE 0x10 + +#define SSR_TDRE 0x80 +#define SSR_RDRF 0x40 +#define SSR_ORER 0x20 +#define SSR_FER 0x10 +#define SSR_PER 0x08 +#define SSR_TEND 0x04 + +#define SMR_CM 0x80 +#define SMR_CHR 0x40 +#define SMR_PE 0x20 +#define SMR_PM 0x10 +#define SMR_STOP 0x08 +#define SMR_MP 0x04 +#define SMR_CKS1 0x02 +#define SMR_CKS0 0x01 + +#define TCSR_CMFB 0x80 +#define TCSR_CMFA 0x40 +#define TCSR_OVF 0x20 + +#define TCR_CMIEB 0x80 +#define TCR_CMIEA 0x40 +#define TCR_OVIE 0x20 + +#define TSR_TCFD 0x80 +#define TSR_TCFU 0x20 +#define TSR_TCFV 0x10 +#define TSR_TGFD 0x08 +#define TSR_TGFC 0x04 +#define TSR_TGFB 0x02 +#define TSR_TGFA 0x01 + +#define TIER_TCIEU 0x20 +#define TIER_TCIEV 0x10 +#define TIER_TGIED 0x08 +#define TIER_TGIEC 0x04 +#define TIER_TGIEB 0x02 +#define TIER_TGIEA 0x01 + +#define DTC_MRA_MD_NORMAL 0 +#define DTC_MRA_MD_REPEAT 1 +#define DTC_MRA_MD_BLOCK 2 + +#define DTC_MRA_SM1 0x80 +#define DTC_MRA_SM0 0x40 +#define DTC_MRA_DM1 0x20 +#define DTC_MRA_DM0 0x10 +#define DTC_MRA_DTS 0x02 + +#define DTC_MRB_CHNE 0x80 +#define DTC_MRB_DISEL 0x40 +#define DTC_MRB_CHNS 0x20 + +#define DMABCRL_DTME1 0x80 +#define DMABCRL_DTE1 0x40 +#define DMABCRL_DTME0 0x20 +#define DMABCRL_DTE0 0x10 +#define DMABCRL_DTIE1B 0x08 +#define DMABCRL_DTIE1A 0x04 +#define DMABCRL_DTIE0B 0x02 +#define DMABCRL_DTIE0A 0x01 + +#define ADCSR_ADF 0x80 +#define ADCSR_ADIE 0x40 +#define ADCSR_ADST 0x20 +#define ADCSR_SCAN 0x10 + +enum +{ + PIN_P10, PIN_P11, PIN_P12, PIN_P13, PIN_P14, PIN_P15, PIN_P16, PIN_P17, + PIN_P20, PIN_P21, PIN_P22, PIN_P23, PIN_P24, PIN_P25, PIN_P26, PIN_P27, + PIN_P30, PIN_P31, PIN_P32, PIN_P33, PIN_P34, PIN_P35, + PIN_P40, PIN_P41, PIN_P42, PIN_P43, PIN_P44, PIN_P45, PIN_P46, PIN_P47, + PIN_P50, PIN_P51, PIN_P52, PIN_P53, + PIN_P60, PIN_P61, PIN_P62, PIN_P63, PIN_P64, PIN_P65, PIN_P66, PIN_P67, + PIN_PA0, PIN_PA1, PIN_PA2, PIN_PA3, PIN_PA4, PIN_PA5, PIN_PA6, PIN_PA7, + PIN_PB0, PIN_PB1, PIN_PB2, PIN_PB3, PIN_PB4, PIN_PB5, PIN_PB6, PIN_PB7, + PIN_PC0, PIN_PC1, PIN_PC2, PIN_PC3, PIN_PC4, PIN_PC5, PIN_PC6, PIN_PC7, + PIN_PD0, PIN_PD1, PIN_PD2, PIN_PD3, PIN_PD4, PIN_PD5, PIN_PD6, PIN_PD7, + PIN_PE0, PIN_PE1, PIN_PE2, PIN_PE3, PIN_PE4, PIN_PE5, PIN_PE6, PIN_PE7, + PIN_PF0, PIN_PF1, PIN_PF2, PIN_PF3, PIN_PF4, PIN_PF5, PIN_PF6, PIN_PF7, + PIN_PG0, PIN_PG1, PIN_PG2, PIN_PG3, PIN_PG4 +}; + +#define PIN_TIOCA0 PIN_P10 +#define PIN_TIOCB0 PIN_P11 +#define PIN_TIOCC0 PIN_P12 +#define PIN_TIOCD0 PIN_P13 +#define PIN_TIOCA1 PIN_P14 +#define PIN_TIOCB1 PIN_P15 +#define PIN_TIOCA2 PIN_P16 +#define PIN_TIOCB2 PIN_P17 + +#define PIN_TCLKA PIN_P12 +#define PIN_TCLKB PIN_P13 +#define PIN_TCLKC PIN_P15 +#define PIN_TCLKD PIN_P17 + +#define PIN_TXD0 PIN_P30 +#define PIN_TXD1 PIN_P31 +#define PIN_RXD0 PIN_P32 +#define PIN_RXD1 PIN_P33 +#define PIN_SCK0 PIN_P34 +#define PIN_SCK1 PIN_P35 + +#define PIN_TIOCA3 PIN_P20 +#define PIN_TIOCB3 PIN_P21 +#define PIN_TIOCC3 PIN_P22 +#define PIN_TIOCD3 PIN_P23 +#define PIN_TIOCA4 PIN_P24 +#define PIN_TIOCB4 PIN_P25 +#define PIN_TIOCA5 PIN_P26 +#define PIN_TIOCB5 PIN_P27 + +#define PIN_TMRI0 PIN_P22 +#define PIN_TMCI0 PIN_P23 +#define PIN_TMRI1 PIN_P24 +#define PIN_TMCI1 PIN_P25 +#define PIN_TMO0 PIN_P26 +#define PIN_TMO1 PIN_P27 + +const int TPU_0_DIV[] = { 1, 4, 16, 64, 0, 0, 0,0 }; +const int TPU_1_DIV[] = { 1, 4, 16, 64, 0, 0, 256, 0 }; +const int TPU_2_DIV[] = { 1, 4, 16, 64, 0, 0, 0, 1024 }; +const int TPU_3_DIV[] = { 1, 4, 16, 64, 0, 1024, 256, 4096 }; +const int TPU_4_DIV[] = { 1, 4, 16, 64, 0, 0, 1024, 0 }; +const int TPU_5_DIV[] = { 1, 4, 16, 64, 0, 0, 256, 0 }; + +const int H8S_IO_SMR[] = { H8S_IO_SMR0, H8S_IO_SMR1, H8S_IO_SMR2 }; +const int H8S_IO_BRR[] = { H8S_IO_BRR0, H8S_IO_BRR1, H8S_IO_BRR2 }; +const int H8S_IO_SCR[] = { H8S_IO_SCR0, H8S_IO_SCR1, H8S_IO_SCR2 }; +const int H8S_IO_TDR[] = { H8S_IO_TDR0, H8S_IO_TDR1, H8S_IO_TDR2 }; +const int H8S_IO_SSR[] = { H8S_IO_SSR0, H8S_IO_SSR1, H8S_IO_SSR2 }; +const int H8S_IO_RDR[] = { H8S_IO_RDR0, H8S_IO_RDR1, H8S_IO_RDR2 }; + +const int H8S_INT_TXI[] = { H8S_INT_TXI0, H8S_INT_TXI1, H8S_INT_TXI2 }; +const int H8S_INT_RXI[] = { H8S_INT_RXI0, H8S_INT_RXI1, H8S_INT_RXI2 }; + +const int H8S_IO_TCORA[] = { H8S_IO_TCORA0, H8S_IO_TCORA1 }; +const int H8S_IO_TCORB[] = { H8S_IO_TCORB0, H8S_IO_TCORB1 }; +const int H8S_IO_TCR[] = { H8S_IO_TCR0, H8S_IO_TCR1 }; +const int H8S_IO_TCNT[] = { H8S_IO_TCNT0, H8S_IO_TCNT1 }; +const int H8S_IO_TCSR[] = { H8S_IO_TCSR0, H8S_IO_TCSR1 }; + +const int H8S_INT_OVI[] = { H8S_INT_OVI0, H8S_INT_OVI1 }; +const int H8S_INT_CMIA[] = { H8S_INT_CMIA0, H8S_INT_CMIA1 }; +const int H8S_INT_CMIB[] = { H8S_INT_CMIB0, H8S_INT_CMIB1 }; + +const int H8S_IO_TGRA_H[] = { H8S_IO_TGR0A_H, H8S_IO_TGR1A_H, H8S_IO_TGR2A_H, H8S_IO_TGR3A_H, H8S_IO_TGR4A_H, H8S_IO_TGR5A_H }; +const int H8S_IO_TGRA_L[] = { H8S_IO_TGR0A_L, H8S_IO_TGR1A_L, H8S_IO_TGR2A_L, H8S_IO_TGR3A_L, H8S_IO_TGR4A_L, H8S_IO_TGR5A_L }; +const int H8S_IO_TGRB_H[] = { H8S_IO_TGR0B_H, H8S_IO_TGR1B_H, H8S_IO_TGR2B_H, H8S_IO_TGR3B_H, H8S_IO_TGR4B_H, H8S_IO_TGR5B_H }; +const int H8S_IO_TGRB_L[] = { H8S_IO_TGR0B_L, H8S_IO_TGR1B_L, H8S_IO_TGR2B_L, H8S_IO_TGR3B_L, H8S_IO_TGR4B_L, H8S_IO_TGR5B_L }; +const int H8S_IO_TGRC_H[] = { H8S_IO_TGR0C_H, 0, 0, H8S_IO_TGR3C_H, 0, 0 }; +const int H8S_IO_TGRC_L[] = { H8S_IO_TGR0C_L, 0, 0, H8S_IO_TGR3C_L, 0, 0 }; +const int H8S_IO_TGRD_H[] = { H8S_IO_TGR0D_H, 0, 0, H8S_IO_TGR3D_H, 0, 0 }; +const int H8S_IO_TGRD_L[] = { H8S_IO_TGR0D_L, 0, 0, H8S_IO_TGR3D_L, 0, 0 }; +const int H8S_IO_TCNT_H[] = { H8S_IO_TCNT0_H, H8S_IO_TCNT1_H, H8S_IO_TCNT2_H, H8S_IO_TCNT3_H, H8S_IO_TCNT4_H, H8S_IO_TCNT5_H }; +const int H8S_IO_TCNT_L[] = { H8S_IO_TCNT0_L, H8S_IO_TCNT1_L, H8S_IO_TCNT2_L, H8S_IO_TCNT3_L, H8S_IO_TCNT4_L, H8S_IO_TCNT5_L }; +const int H8S_IO_TIOR_H[] = { H8S_IO_TIOR0_H, H8S_IO_TIOR1, H8S_IO_TIOR2, H8S_IO_TIOR3_H, H8S_IO_TIOR4, H8S_IO_TIOR5 }; +const int H8S_IO_TIOR_L[] = { H8S_IO_TIOR0_L, 0, 0, H8S_IO_TIOR3_L, 0, 0 }; +const int H8S_IO_TTCR[] = { H8S_IO_TTCR0, H8S_IO_TTCR1, H8S_IO_TTCR2, H8S_IO_TTCR3, H8S_IO_TTCR4, H8S_IO_TTCR5 }; +const int H8S_IO_TIER[] = { H8S_IO_TIER0, H8S_IO_TIER1, H8S_IO_TIER2, H8S_IO_TIER3, H8S_IO_TIER4, H8S_IO_TIER5 }; +const int H8S_IO_TSR[] = { H8S_IO_TSR0, H8S_IO_TSR1, H8S_IO_TSR2, H8S_IO_TSR3, H8S_IO_TSR4, H8S_IO_TSR5 }; + +const int H8S_INT_TCIV[] = { H8S_INT_TCI0V, H8S_INT_TCI1V, H8S_INT_TCI2V, H8S_INT_TCI3V, H8S_INT_TCI4V, H8S_INT_TCI5V }; +const int H8S_INT_TCIU[] = { 0, H8S_INT_TCI1U, H8S_INT_TCI2U, 0, H8S_INT_TCI4U, H8S_INT_TCI5U }; +const int H8S_INT_TGIA[] = { H8S_INT_TGI0A, H8S_INT_TGI1A, H8S_INT_TGI2A, H8S_INT_TGI3A, H8S_INT_TGI4A, H8S_INT_TGI5A }; +const int H8S_INT_TGIB[] = { H8S_INT_TGI0B, H8S_INT_TGI1B, H8S_INT_TGI2B, H8S_INT_TGI3B, H8S_INT_TGI4B, H8S_INT_TGI5B }; +const int H8S_INT_TGIC[] = { H8S_INT_TGI0C, 0, 0, H8S_INT_TGI3C, 0, 0 }; +const int H8S_INT_TGID[] = { H8S_INT_TGI0D, 0, 0, H8S_INT_TGI3D, 0, 0 }; + +const int PIN_TIOCA[] = { PIN_TIOCA0, PIN_TIOCA1, PIN_TIOCA2, PIN_TIOCA3, PIN_TIOCA4, PIN_TIOCA5 }; +const int PIN_TIOCB[] = { PIN_TIOCB0, PIN_TIOCB1, PIN_TIOCB2, PIN_TIOCB3, PIN_TIOCB4, PIN_TIOCB5 }; +const int PIN_TIOCC[] = { PIN_TIOCC0, 0, 0, PIN_TIOCC3, 0, 0 }; +const int PIN_TIOCD[] = { PIN_TIOCD0, 0, 0, PIN_TIOCD3, 0, 0 }; + +const int TCR_CCLR_AND[] = { 7, 3, 3, 7, 3, 3 }; + +// prototypes + +void h8s_tmr_x_reset( h83xx_state *h8, int x); +void h8s_tpu_x_reset( h83xx_state *h8, int x); +void h8s_tpu_x_tick( h83xx_state *h8, int x); + +//////////// +// DTVECR // +//////////// + +#define DTVECR_ADDR(x) (0x400 + (x << 1)) + +/////////////// +// MEMCONV.H // +/////////////// + +static TIMER_CALLBACK( h8s_tmr_callback ); +static TIMER_CALLBACK( h8s_tpu_callback ); +static TIMER_CALLBACK( h8s_sci_callback ); + +///////////// +// TIMER.C // +///////////// + +UINT16 ptr_read_16( void *ptr) +{ + return (*(((UINT8*)ptr) + 0) << 8) | (*(((UINT8*)ptr) + 1) << 0); +} + +void ptr_write_16( void *ptr, UINT16 data) +{ + *(((UINT8*)ptr) + 0) = (data >> 8) & 0xFF; + *(((UINT8*)ptr) + 1) = (data >> 0) & 0xFF; +} + +int device_icount_min_timer_icount1( h83xx_state *h8, emu_timer *timer) +{ + return (timer->elapsed() * h8->device->unscaled_clock()).as_double(); +} + +void h8s2xxx_interrupt_request(h83xx_state *h8, UINT32 vecnum) +{ + UINT8 idx, bit; + idx = vecnum >> 5; + bit = vecnum & 0x1F; + h8->irq_req[idx] |= (1 << bit); +} + +void h8s_dtce_execute(h83xx_state *h8, UINT32 addr_dtce, UINT8 mask_dtce, UINT32 addr_dtvecr) +{ + UINT32 data[3], dtc_vect, dtc_sar, dtc_dar, cnt, i; + UINT8 dtc_mra, dtc_mrb, sz; + UINT16 dtc_cra, dtc_crb; + // get dtc info + dtc_vect = 0xFF0000 | h8->program->read_word(addr_dtvecr); + data[0] = h8->program->read_dword( dtc_vect + 0); + data[1] = h8->program->read_dword( dtc_vect + 4); + data[2] = h8->program->read_dword( dtc_vect + 8); + dtc_mra = (data[0] >> 24) & 0xFF; + dtc_sar = (data[0] >> 0) & 0xFFFFFF; + dtc_mrb = (data[1] >> 24) & 0xFF; + dtc_dar = (data[1] >> 0) & 0xFFFFFF; + dtc_cra = (data[2] >> 16) & 0xFFFF; + dtc_crb = (data[2] >> 0) & 0xFFFF; + verboselog( h8->device->machine(), 3, "dtc : vect %08X mra %02X sar %08X mrb %02X dar %08X cra %04X crb %04X\n", dtc_vect, dtc_mra, dtc_sar, dtc_mrb, dtc_dar, dtc_cra, dtc_crb); + // execute + if ((dtc_mra & 0x0E) != 0x00) fatalerror("H8S: dtc unsupported MRA %x\n", dtc_mra&0x0e); + sz = 1 << (dtc_mra & 0x01); + cnt = dtc_cra; + for (i=0;i<cnt;i++) + { + if (dtc_sar == H8S_IO_ADDR( H8S_IO_RDR1)) h8->program->write_byte( H8S_IO_ADDR( H8S_IO_SSR1), h8->program->read_byte( H8S_IO_ADDR( H8S_IO_SSR1)) & (~H8S_SSR_TDRE)); + if (dtc_mra & 0x01) h8->program->write_word( dtc_dar, h8->program->read_word( dtc_sar)); else h8->program->write_byte( dtc_dar, h8->program->read_byte( dtc_sar)); + if (dtc_dar == H8S_IO_ADDR( H8S_IO_TDR0)) h8->program->write_byte( H8S_IO_ADDR( H8S_IO_SSR0), h8->program->read_byte( H8S_IO_ADDR( H8S_IO_SSR0)) & (~H8S_SSR_TDRE)); + if (dtc_mra & 0x80) { if (dtc_mra & 0x40) dtc_sar -= sz; else dtc_sar += sz; } + if (dtc_mra & 0x20) { if (dtc_mra & 0x10) dtc_dar -= sz; else dtc_dar += sz; } + } + h8->program->write_byte( addr_dtce, h8->program->read_byte( addr_dtce) & (~mask_dtce)); +} + +void h8s_dtce_check(h83xx_state *h8, int vecnum) +{ + UINT32 dtce = 0; + int bit = 0; + // get dtce info + switch (vecnum) + { + // DTCEA + case H8S_INT_IRQ0 : dtce = H8S_IO_DTCEA; bit = 7; break; + case H8S_INT_IRQ1 : dtce = H8S_IO_DTCEA; bit = 6; break; + case H8S_INT_IRQ2 : dtce = H8S_IO_DTCEA; bit = 5; break; + case H8S_INT_IRQ3 : dtce = H8S_IO_DTCEA; bit = 4; break; + case H8S_INT_IRQ4 : dtce = H8S_IO_DTCEA; bit = 3; break; + case H8S_INT_IRQ5 : dtce = H8S_IO_DTCEA; bit = 2; break; + case H8S_INT_IRQ6 : dtce = H8S_IO_DTCEA; bit = 1; break; + case H8S_INT_IRQ7 : dtce = H8S_IO_DTCEA; bit = 0; break; + // DTCEB + case H8S_INT_ADI : dtce = H8S_IO_DTCEB; bit = 6; break; + case H8S_INT_TGI0A : dtce = H8S_IO_DTCEB; bit = 5; break; + case H8S_INT_TGI0B : dtce = H8S_IO_DTCEB; bit = 4; break; + case H8S_INT_TGI0C : dtce = H8S_IO_DTCEB; bit = 3; break; + case H8S_INT_TGI0D : dtce = H8S_IO_DTCEB; bit = 2; break; + case H8S_INT_TGI1A : dtce = H8S_IO_DTCEB; bit = 1; break; + case H8S_INT_TGI1B : dtce = H8S_IO_DTCEB; bit = 0; break; + // DTCEC + case H8S_INT_TGI2A : dtce = H8S_IO_DTCEC; bit = 7; break; + case H8S_INT_TGI2B : dtce = H8S_IO_DTCEC; bit = 6; break; + // DTCED + case H8S_INT_CMIA0 : dtce = H8S_IO_DTCED; bit = 3; break; + case H8S_INT_CMIB0 : dtce = H8S_IO_DTCED; bit = 2; break; + case H8S_INT_CMIA1 : dtce = H8S_IO_DTCED; bit = 1; break; + case H8S_INT_CMIB1 : dtce = H8S_IO_DTCED; bit = 0; break; + // DTCEE + case H8S_INT_RXI0 : dtce = H8S_IO_DTCEE; bit = 3; break; + case H8S_INT_TXI0 : dtce = H8S_IO_DTCEE; bit = 2; break; + case H8S_INT_RXI1 : dtce = H8S_IO_DTCEE; bit = 1; break; + case H8S_INT_TXI1 : dtce = H8S_IO_DTCEE; bit = 0; break; + // DTCEF + case H8S_INT_RXI2 : dtce = H8S_IO_DTCEF; bit = 7; break; + case H8S_INT_TXI2 : dtce = H8S_IO_DTCEF; bit = 6; break; + } + // execute + if ((dtce != 0) && (h8->per_regs[dtce] & (1 << bit))) h8s_dtce_execute(h8, H8S_IO_ADDR( dtce), (1 << bit), DTVECR_ADDR( vecnum)); +} + +void h8s_periph_reset(h83xx_state *h8) +{ + const int tpu_max = (h8->device->type() == H8S2323) ? 6 : 3; + if ((h8->device->type() == H8S2241) || (h8->device->type() == H8S2246)) + { + memcpy( h8->per_regs, H8S_RESET_H8S_IO_224x, sizeof( h8->per_regs)); + } + else if (h8->device->type() == H8S2323) + { + memcpy( h8->per_regs, H8S_RESET_H8S_IO_2323, sizeof( h8->per_regs)); + } + for (int i = 0; i < 2; i++) h8s_tmr_x_reset( h8, i); + for (int i = 0; i < tpu_max; i++) h8s_tpu_x_reset( h8, i); +} + +///////////////// +// TIMER 8-BIT // +///////////////// + +void h8s_tmr_init(h83xx_state *h8) +{ + for (int i = 0; i < 2; i++) + { + h8->tmr[i].timer = h8->device->machine().scheduler().timer_alloc(FUNC(h8s_tmr_callback), h8); + h8->tmr[i].timer->adjust(attotime::never, i); + } +} + +void h8s_tmr_x_reset( h83xx_state *h8, int x) +{ + H8S2XXX_TMR *tmr = &h8->tmr[x]; + tmr->cycles_per_tick = 0; + tmr->timer->adjust(attotime::never, x); +} + +UINT64 h8s_tmr_x_calculate_ticks( h83xx_state *h8, int x, UINT8 tcnt) +{ + UINT64 cycles1, cycles2; + UINT8 tcor; + // overflow + if (tcnt == 0) cycles1 = 0xFF + 1; else cycles1 = (UINT8)(0xFF - tcnt + 1); + // tcora + tcor = h8->per_regs[H8S_IO_TCORA[x]]; + if (tcnt == tcor) cycles2 = 0xFF + 1; else cycles2 = (UINT8)(tcor - tcnt); + if ((cycles2 > 0) && (cycles2 < cycles1)) cycles1 = cycles2; + // tcorb + tcor = h8->per_regs[H8S_IO_TCORB[x]]; + if (tcnt == tcor) cycles2 = 0xFF + 1; else cycles2 = (UINT8)(tcor - tcnt); + if ((cycles2 > 0) && (cycles2 < cycles1)) cycles1 = cycles2; + // done + return cycles1; +} + +void h8s_tmr_x_update( h83xx_state *h8, int x) +{ + H8S2XXX_TMR *tmr = &h8->tmr[x]; + UINT64 cycles; + int div = 0; + UINT8 tcr, tcnt; + tcr = h8->per_regs[H8S_IO_TCR[x]]; + switch ((tcr >> 0) & 7) + { + case 1 : div = 8; break; + case 2 : div = 64; break; + case 3 : div = 8192; break; +// default : OS_MessageBox( NULL, "tmr_x_update", "error", 0); break; + } + tmr->cycles_per_tick = div; + tcnt = h8->per_regs[H8S_IO_TCNT[x]]; + verboselog( h8->device->machine(), 5, "TMR %d - update (div %d tcnt %02X)\n", x, div, tcnt); + // update timer + cycles = h8s_tmr_x_calculate_ticks( h8, x, tcnt) * tmr->cycles_per_tick; + tmr->timer_cycles = cycles; + tmr->timer->adjust(attotime::from_hz(h8->device->unscaled_clock() / cycles), x); +} + +UINT8 h8s_tmr_x_calculate_tcnt( h83xx_state *h8, int x) +{ + H8S2XXX_TMR *tmr = &h8->tmr[x]; + UINT8 tcnt; + tcnt = h8->per_regs[H8S_IO_TCNT[x]]; + if (tmr->timer->enabled()) + { + tcnt = (UINT8)(tcnt + ((device_icount_min_timer_icount1( h8, tmr->timer)) / tmr->cycles_per_tick)); + } + return tcnt; +} + +void h8s_tmr_x_start( h83xx_state *h8, int x) +{ + verboselog( h8->device->machine(), 5, "TMR %d - start\n", x); + // ... + h8s_tmr_x_update( h8, x); +} + +void h8s_tmr_x_stop( h83xx_state *h8, int x) +{ + H8S2XXX_TMR *tmr = &h8->tmr[x]; + UINT8 tcnt; + // ... + verboselog( h8->device->machine(), 5, "TMR %d - stop\n", x); + // calculate tcnt + tcnt = h8s_tmr_x_calculate_tcnt( h8, x); + // update tcnt + h8->per_regs[H8S_IO_TCNT[x]] = tcnt; + // disable timer + tmr->timer->reset(); +} + +UINT8 h8s_tmr_x_tcnt_change( h83xx_state *h8, int x, UINT8 tcnt) +{ + UINT8 tcr, tcor; + int clear = 0; + // ... + verboselog( h8->device->machine(), 9, "TMR %d - tmr_x_tcnt_change (%02X)\n", x, tcnt); + // ... + tcr = h8->per_regs[H8S_IO_TCR[x]]; + // overflow + if (tcnt == 0) + { + verboselog( h8->device->machine(), 9, "TMR %d - overflow match\n", x); + h8->per_regs[H8S_IO_TCSR[x]] |= TCSR_OVF; + if ((tcr & TCR_OVIE) != 0) + { + h8s2xxx_interrupt_request( h8, H8S_INT_OVI[x]); + } + } + // tcora + tcor = h8->per_regs[H8S_IO_TCORA[x]]; + if (tcnt == tcor) + { + verboselog( h8->device->machine(), 9, "TMR %d - tcora match\n", x); + h8->per_regs[H8S_IO_TCSR[x]] |= TCSR_CMFA; + if ((tcr & TCR_CMIEA) != 0) + { + h8s2xxx_interrupt_request( h8, H8S_INT_CMIA[x]); + } + if (((tcr >> 3) & 3) == 1) // CCLR 1 -> "clear by compare match a" + { + clear = 1; + } + } + // tcorb + tcor = h8->per_regs[H8S_IO_TCORB[x]]; + if (tcnt == tcor) + { + verboselog( h8->device->machine(), 9, "TMR %d - tcorb match\n", x); + h8->per_regs[H8S_IO_TCSR[x]] |= TCSR_CMFB; + if ((tcr & TCR_CMIEB) != 0) + { + h8s2xxx_interrupt_request( h8, H8S_INT_CMIB[x]); + } + if (((tcr >> 3) & 3) == 2) // CCLR 2 -> "clear by compare match b" + { + clear = 1; + } + } + // ... + if (clear) + { + verboselog( h8->device->machine(), 5, "TMR %d - tcnt clear\n", x); + tcnt = 0; + } + // ... + return tcnt; +} + +void h8s_tmr_x_callback( h83xx_state *h8, int x) +{ + H8S2XXX_TMR *tmr = &h8->tmr[x]; + UINT64 cycles; + UINT8 tcnt; + // calculate tcnt + tcnt = h8->per_regs[H8S_IO_TCNT[x]]; + tcnt = (UINT8)(tcnt + tmr->timer_cycles / tmr->cycles_per_tick); + // ... + tcnt = h8s_tmr_x_tcnt_change( h8, x, tcnt); + // update tcnt + h8->per_regs[H8S_IO_TCNT[x]] = tcnt; + // update timer + cycles = h8s_tmr_x_calculate_ticks( h8, x, tcnt) * tmr->cycles_per_tick; + tmr->timer_cycles = cycles; + tmr->timer->adjust(attotime::from_hz(h8->device->unscaled_clock() / cycles), x); +} + +void h8s_tmr_x_write_tcr( h83xx_state *h8, int x, UINT8 data) +{ + UINT8 old_data = h8->per_regs[H8S_IO_TCR[x]]; + h8->per_regs[H8S_IO_TCR[x]] = data; + if ((data & 0x07) != (old_data & 0x07)) + { + if ((data & 0x07) != 0) + { + h8s_tmr_x_start( h8, x); + } + else + { + h8s_tmr_x_stop( h8, x); + } + } +} + +void h8s_tmr_x_write_tcnt( h83xx_state *h8, int x, UINT8 data) +{ + H8S2XXX_TMR *tmr = &h8->tmr[x]; + h8->per_regs[H8S_IO_TCNT[x]] = data; + if (tmr->timer->enabled()) + { + h8s_tmr_x_update( h8, x); + } +} + +void h8s_tmr_x_write_tcor( h83xx_state *h8, int x) +{ + H8S2XXX_TMR *tmr = &h8->tmr[x]; + if ((tmr->timer->enabled()) && (tmr->cycles_per_tick != 0)) + { + UINT8 tcnt1, tcnt2; + UINT64 cycles; + tcnt1 = h8->per_regs[H8S_IO_TCNT[x]]; + tcnt2 = (UINT8)(tcnt1 + ((device_icount_min_timer_icount1( h8, tmr->timer)) / tmr->cycles_per_tick)); + cycles = h8s_tmr_x_calculate_ticks( h8, x, tcnt2) * tmr->cycles_per_tick; + cycles = cycles + (tcnt2 - tcnt1) * tmr->cycles_per_tick; + tmr->timer_cycles = cycles; + tmr->timer->adjust(attotime::from_hz(h8->device->unscaled_clock() / cycles), x); + } +} + +UINT8 h8s_tmr_x_read_tcnt( h83xx_state *h8, int x) +{ + return h8s_tmr_x_calculate_tcnt( h8, x); +} + +void h8s_tmr_x_write_tcora( h83xx_state *h8, int x, UINT8 data) +{ + h8->per_regs[H8S_IO_TCORA[x]] = data; + h8s_tmr_x_write_tcor( h8, x); +} + +void h8s_tmr_x_write_tcorb( h83xx_state *h8, int x, UINT8 data) +{ + h8->per_regs[H8S_IO_TCORB[x]] = data; + h8s_tmr_x_write_tcor( h8, x); +} + +static TIMER_CALLBACK( h8s_tmr_callback) +{ + h83xx_state *h8 = (h83xx_state *)ptr; + h8s_tmr_x_callback( h8, param); +} + +////////////////// +// TIMER 16-BIT // +////////////////// + +void h8s_tpu_init(h83xx_state *h8) +{ + const int tpu_max = (h8->device->type() == H8S2323) ? 6 : 3; + for (int i = 0; i < tpu_max; i++) + { + h8->tpu[i].timer = h8->device->machine().scheduler().timer_alloc(FUNC(h8s_tpu_callback), h8); + h8->tpu[i].timer->adjust(attotime::never, i); + } +} + +void h8s_tpu_x_reset( h83xx_state *h8, int x) +{ + H8S2XXX_TPU *tpu = &h8->tpu[x]; + tpu->cycles_per_tick = 0; + tpu->timer->reset(); +} + +UINT16 h8s_tpu_x_calculate_tcnt( h83xx_state *h8, int x) +{ + H8S2XXX_TPU *tpu = &h8->tpu[x]; + UINT16 tcnt; + tcnt = ptr_read_16( h8->per_regs + H8S_IO_TCNT_H[x]); + if ((tpu->timer->enabled()) && (tpu->cycles_per_tick > 0)) + { + tcnt = (UINT16)(tcnt + ((device_icount_min_timer_icount1( h8, tpu->timer)) / tpu->cycles_per_tick)); + } + return tcnt; +} + +UINT64 h8s_tpu_x_calculate_ticks( h83xx_state *h8, int x, UINT16 tcnt) +{ + UINT64 cycles1, cycles2; + UINT16 tgr; + // overflow + if (tcnt == 0) cycles1 = 0xFFFF + 1; else cycles1 = (UINT16)(0xFFFF - tcnt + 1); + // tgra + tgr = ptr_read_16( h8->per_regs + H8S_IO_TGRA_H[x]); + if (tcnt == tgr) cycles2 = 0xFFFF + 1; else cycles2 = (UINT16)(tgr - tcnt); + if ((cycles2 > 0) && (cycles2 < cycles1)) cycles1 = cycles2; + // tgrb + tgr = ptr_read_16( h8->per_regs + H8S_IO_TGRB_H[x]); + if (tcnt == tgr) cycles2 = 0xFFFF + 1; else cycles2 = (UINT16)(tgr - tcnt); + if ((cycles2 > 0) && (cycles2 < cycles1)) cycles1 = cycles2; + // tgrc + if ((x == 0) || (x == 3)) + { + tgr = ptr_read_16( h8->per_regs + H8S_IO_TGRC_H[x]); + if (tcnt == tgr) cycles2 = 0xFFFF + 1; else cycles2 = (UINT16)(tgr - tcnt); + if ((cycles2 > 0) && (cycles2 < cycles1)) cycles1 = cycles2; + } + // tgrd + if ((x == 0) || (x == 3)) + { + tgr = ptr_read_16( h8->per_regs + H8S_IO_TGRD_H[x]); + if (tcnt == tgr) cycles2 = 0xFFFF + 1; else cycles2 = (UINT16)(tgr - tcnt); + if ((cycles2 > 0) && (cycles2 < cycles1)) cycles1 = cycles2; + } + // done + return cycles1; +} + +void h8s_pin_write( h83xx_state *h8, int pin, int data) +{ + switch (pin) + { + case PIN_TIOCB1 : + { + UINT8 p1dr; + p1dr = h8->per_regs[H8S_IO_P1DR]; + if (data) p1dr |= H8S_P1_TIOCB1; else p1dr &= ~H8S_P1_TIOCB1; + h8->io->write_byte(H8S_IO_ADDR(H8S_IO_P1DR), p1dr); + h8->per_regs[H8S_IO_P1DR] = p1dr; + } + break; + } +} + +int h8s_pin_read( h83xx_state *h8, int pin) +{ + switch (pin) + { + case PIN_TIOCB1 : return (h8->per_regs[H8S_IO_P1DR] & H8S_P1_TIOCB1) ? 1 : 0; + } + return 0; +} + +void h8s_tioc_pin_update( h83xx_state *h8, int io, int pin) +{ + switch (io) + { + case 1 : h8s_pin_write( h8, pin, 0); break; + case 2 : h8s_pin_write( h8, pin, 1); break; + case 3 : h8s_pin_write( h8, pin, h8s_pin_read( h8, pin) ? 0 : 1); break; + case 5 : h8s_pin_write( h8, pin, 0); break; + case 6 : h8s_pin_write( h8, pin, 1); break; + case 7 : h8s_pin_write( h8, pin, h8s_pin_read( h8, pin) ? 0 : 1); break; + } +} + +void h8s_tioc_pin_reset( h83xx_state *h8, int io, int pin) +{ + switch (io) + { + case 1 : h8s_pin_write( h8, pin, 0); break; + case 2 : h8s_pin_write( h8, pin, 0); break; + case 3 : h8s_pin_write( h8, pin, 0); break; + case 5 : h8s_pin_write( h8, pin, 1); break; + case 6 : h8s_pin_write( h8, pin, 1); break; + case 7 : h8s_pin_write( h8, pin, 1); break; + } +} + +void h8s_tpu_x_tioc_reset( h83xx_state *h8, int x) +{ + UINT8 tior; + int cclr; + // ... + cclr = (h8->per_regs[H8S_IO_TTCR[x]] >> 5) & TCR_CCLR_AND[x]; + // tioca & tiocb + tior = h8->per_regs[H8S_IO_TIOR_H[x]]; + if (cclr != 1) h8s_tioc_pin_reset( h8, (tior >> 0) & 0x0F, PIN_TIOCA[x]); + if (cclr != 2) h8s_tioc_pin_reset( h8, (tior >> 4) & 0x0F, PIN_TIOCB[x]); + // tiocc & tiocd + if ((x == 0) || (x == 3)) + { + tior = h8->per_regs[H8S_IO_TIOR_L[x]]; + if (cclr != 5) h8s_tioc_pin_reset( h8, (tior >> 0) & 0x0F, PIN_TIOCC[x]); + if (cclr != 6) h8s_tioc_pin_reset( h8, (tior >> 4) & 0x0F, PIN_TIOCD[x]); + } +} + +void h8s_tpu_x_overflow( h83xx_state *h8, int x) +{ + if (x == 2) + { + UINT8 tcr = h8->per_regs[H8S_IO_TTCR[1]]; + if (((tcr >> 0) & 7) == 7) + { + h8s_tpu_x_tick( h8, 1); + } + } + if (x == 5) + { + UINT8 tcr = h8->per_regs[H8S_IO_TTCR[4]]; + if (((tcr >> 0) & 7) == 7) + { + h8s_tpu_x_tick( h8, 4); + } + } +} + +UINT16 h8s_tpu_x_tcnt_change( h83xx_state *h8, int x, UINT16 tcnt) +{ + UINT16 tgr; + UINT8 tcr, tier, tior; + int clear = 0; + // ... + verboselog( h8->device->machine(), 9, "TPU %d - tpu_x_tcnt_change (%04X)\n", x, tcnt); + // ... + tcr = h8->per_regs[H8S_IO_TTCR[x]]; + tier = h8->per_regs[H8S_IO_TIER[x]]; + // overflow + if (tcnt == 0) + { + verboselog( h8->device->machine(), 9, "TPU %d - overflow match\n", x); + h8->per_regs[H8S_IO_TSR[x]] |= TSR_TCFV; + if (tier & TIER_TCIEV) + { + h8s2xxx_interrupt_request( h8, H8S_INT_TCIV[x]); + } + h8s_tpu_x_overflow( h8, x); + } + // tgra + tgr = ptr_read_16( h8->per_regs + H8S_IO_TGRA_H[x]); + if (tcnt == tgr) + { + verboselog( h8->device->machine(), 9, "TPU %d - tgra match\n", x); + h8->per_regs[H8S_IO_TSR[x]] |= TSR_TGFA; + if (tier & TIER_TGIEA) + { + h8s2xxx_interrupt_request( h8, H8S_INT_TGIA[x]); + } + if (((tcr >> 5) & TCR_CCLR_AND[x]) == 1) // CCLR 1 -> "TCNT cleared by TGRA compare match/input capture" + { + clear = 1; + } + else + { + tior = h8->per_regs[H8S_IO_TIOR_H[x]]; + h8s_tioc_pin_update( h8, (tior >> 0) & 0x0F, PIN_TIOCA[x]); + } + } + // tgrb + tgr = ptr_read_16( h8->per_regs + H8S_IO_TGRB_H[x]); + if (tcnt == tgr) + { + verboselog( h8->device->machine(), 9, "TPU %d - tgrb match\n", x); + h8->per_regs[H8S_IO_TSR[x]] |= TSR_TGFB; + if (tier & TIER_TGIEB) + { + h8s2xxx_interrupt_request( h8, H8S_INT_TGIB[x]); + } + if (((tcr >> 5) & TCR_CCLR_AND[x]) == 2) // CCLR 2 -> "TCNT cleared by TGRB compare match/input capture" + { + clear = 1; + } + else + { + tior = h8->per_regs[H8S_IO_TIOR_H[x]]; + h8s_tioc_pin_update( h8, (tior >> 4) & 0x0F, PIN_TIOCB[x]); + } + } + // tgrc + if ((x == 0) || (x == 3)) + { + tgr = ptr_read_16( h8->per_regs + H8S_IO_TGRC_H[x]); + if (tcnt == tgr) + { + verboselog( h8->device->machine(), 9, "TPU %d - tgrc match\n", x); + h8->per_regs[H8S_IO_TSR[x]] |= TSR_TGFC; + if (tier & TIER_TGIEC) + { + h8s2xxx_interrupt_request( h8, H8S_INT_TGIC[x]); + } + if (((tcr >> 5) & TCR_CCLR_AND[x]) == 5) // CCLR 5 -> "TCNT cleared by TGRC compare match/input capture" + { + clear = 1; + } + else + { + tior = h8->per_regs[H8S_IO_TIOR_L[x]]; + h8s_tioc_pin_update( h8, (tior >> 0) & 0x0F, PIN_TIOCC[x]); + } + } + } + // tgrd + if ((x == 0) || (x == 3)) + { + tgr = ptr_read_16( h8->per_regs + H8S_IO_TGRD_H[x]); + if (tcnt == tgr) + { + verboselog( h8->device->machine(), 9, "TPU %d - tgrd match\n", x); + h8->per_regs[H8S_IO_TSR[x]] |= TSR_TGFD; + if (tier & TIER_TGIED) + { + h8s2xxx_interrupt_request( h8, H8S_INT_TGID[x]); + } + if (((tcr >> 5) & TCR_CCLR_AND[x]) == 6) // CCLR 6 -> "TCNT cleared by TGRD compare match/input capture" + { + clear = 1; + } + else + { + tior = h8->per_regs[H8S_IO_TIOR_L[x]]; + h8s_tioc_pin_update( h8, (tior >> 4) & 0x0F, PIN_TIOCD[x]); + } + } + } + // ... + if (clear) + { + verboselog( h8->device->machine(), 9, "TPU %d - tcnt clear\n", x); + h8s_tpu_x_tioc_reset( h8, x); + tcnt = 0; + } + // ... + return tcnt; +} + +void h8s_tpu_x_callback( h83xx_state *h8, int x) +{ + H8S2XXX_TPU *tpu = &h8->tpu[x]; + UINT64 cycles; + UINT16 tcnt; + // calculate tcnt + tcnt = ptr_read_16( h8->per_regs + H8S_IO_TCNT_H[x]); + tcnt = (UINT16)(tcnt + tpu->timer_cycles / tpu->cycles_per_tick); + // ... + tcnt = h8s_tpu_x_tcnt_change( h8, x, tcnt); + // update tcnt + ptr_write_16( h8->per_regs + H8S_IO_TCNT_H[x], tcnt); + // update timer + cycles = h8s_tpu_x_calculate_ticks( h8, x, tcnt) * tpu->cycles_per_tick; + tpu->timer_cycles = cycles; + tpu->timer->adjust(attotime::from_hz(h8->device->unscaled_clock() / cycles), x); +} + +void h8s_tpu_x_tick( h83xx_state *h8, int x) +{ + UINT16 tcnt; + // calculate tcnt + tcnt = ptr_read_16( h8->per_regs + H8S_IO_TCNT_H[x]); + tcnt = (UINT16)(tcnt + 1); + // ... + tcnt = h8s_tpu_x_tcnt_change( h8, x, tcnt); + // update tcnt + ptr_write_16( h8->per_regs + H8S_IO_TCNT_H[x], tcnt); +} + +int h8s_tpu_x_get_div( h83xx_state *h8, int x) +{ + UINT8 tcr; + int tpsc; + const int *TPU_X_DIV[] = { TPU_0_DIV, TPU_1_DIV, TPU_2_DIV, TPU_3_DIV, TPU_4_DIV, TPU_5_DIV }; + tcr = h8->per_regs[H8S_IO_TTCR[x]]; + tpsc = (tcr >> 0) & 7; + return TPU_X_DIV[x][tpsc]; +} + +void h8s_tpu_x_update( h83xx_state *h8, int x) +{ + H8S2XXX_TPU *tpu = &h8->tpu[x]; + // ... + tpu->cycles_per_tick = h8s_tpu_x_get_div( h8, x); + // update timer + if (tpu->cycles_per_tick != 0) + { + UINT16 tcnt; + UINT64 cycles; + tcnt = ptr_read_16( h8->per_regs + H8S_IO_TCNT_H[x]); + cycles = h8s_tpu_x_calculate_ticks( h8, x, tcnt) * tpu->cycles_per_tick; + tpu->timer_cycles = cycles; + tpu->timer->adjust(attotime::from_hz(h8->device->unscaled_clock() / cycles), x); + } + else + { + tpu->timer->reset(); + } +} + +void h8s_tpu_x_start( h83xx_state *h8, int x) +{ + verboselog( h8->device->machine(), 5, "TPU %d - start\n", x); + // ... + h8s_tpu_x_update( h8, x); +} + +void h8s_tpu_x_stop( h83xx_state *h8, int x) +{ + H8S2XXX_TPU *tpu = &h8->tpu[x]; + UINT16 tcnt; + // ... + verboselog( h8->device->machine(), 5, "TPU %d - stop\n", x); + // calculate tcnt + tcnt = h8s_tpu_x_calculate_tcnt( h8, x); + // update tcnt + ptr_write_16( h8->per_regs + H8S_IO_TCNT_H[x], tcnt); + // disable timer + tpu->timer->reset(); +} + +UINT16 h8s_tpu_x_read_tcnt( h83xx_state *h8, int x) +{ + return h8s_tpu_x_calculate_tcnt( h8, x); +} + +void h8s_tpu_x_write_tcnt( h83xx_state *h8, int x, UINT16 data) +{ + H8S2XXX_TPU *tpu = &h8->tpu[x]; + verboselog( h8->device->machine(), 9, "TPU %d - write tcnt (%04X)\n", x, data); + ptr_write_16( h8->per_regs + H8S_IO_TCNT_H[x], data); + if (tpu->timer->enabled()) + { + h8s_tpu_x_update( h8, x); + } +} + +void h8s_tpu_x_write_tgr( h83xx_state *h8, int x) +{ + H8S2XXX_TPU *tpu = &h8->tpu[x]; + if ((tpu->timer->enabled()) && (tpu->cycles_per_tick != 0)) + { + UINT16 tcnt1, tcnt2; + UINT64 cycles; + tcnt1 = ptr_read_16( h8->per_regs + H8S_IO_TCNT_H[x]); + tcnt2 = (UINT16)(tcnt1 + ((device_icount_min_timer_icount1( h8, tpu->timer)) / tpu->cycles_per_tick)); + cycles = h8s_tpu_x_calculate_ticks( h8, x, tcnt2) * tpu->cycles_per_tick; + cycles = cycles + (tcnt2 - tcnt1) * tpu->cycles_per_tick; + tpu->timer_cycles = cycles; + tpu->timer->adjust(attotime::from_hz(h8->device->unscaled_clock() / cycles), x); + } +} + +void h8s_tpu_x_write_tgra( h83xx_state *h8, int x, UINT16 data) +{ + verboselog( h8->device->machine(), 9, "TPU %d - write tgra (%04X)\n", x, data); + ptr_write_16( h8->per_regs + H8S_IO_TGRA_H[x], data); + h8s_tpu_x_write_tgr( h8, x); +} + +void h8s_tpu_x_write_tgrb( h83xx_state *h8, int x, UINT16 data) +{ + verboselog( h8->device->machine(), 9, "TPU %d - write tgrb (%04X)\n", x, data); + ptr_write_16( h8->per_regs + H8S_IO_TGRB_H[x], data); + h8s_tpu_x_write_tgr( h8, x); +} + +void h8s_tpu_x_write_tgrc( h83xx_state *h8, int x, UINT16 data) +{ + verboselog( h8->device->machine(), 9, "TPU %d - write tgrc (%04X)\n", x, data); + ptr_write_16( h8->per_regs + H8S_IO_TGRC_H[x], data); + h8s_tpu_x_write_tgr( h8, x); +} + +void h8s_tpu_x_write_tgrd( h83xx_state *h8, int x, UINT16 data) +{ + verboselog( h8->device->machine(), 9, "TPU %d - write tgrd (%04X)\n", x, data); + ptr_write_16( h8->per_regs + H8S_IO_TGRD_H[x], data); + h8s_tpu_x_write_tgr( h8, x); +} + +void h8s_tpu_x_write_tior( h83xx_state *h8, int x) +{ + UINT8 tstr; + tstr = h8->per_regs[H8S_IO_TSTR]; + if ((tstr & (1 << x)) == 0) + { + h8s_tpu_x_tioc_reset( h8, x); + } +} + +void h8s_tpu_0_write_tior_h( h83xx_state *h8, UINT8 data) +{ + h8->per_regs[H8S_IO_TIOR0_H] = data; + h8s_tpu_x_write_tior( h8, 0); +} + +void h8s_tpu_0_write_tior_l( h83xx_state *h8, UINT8 data) +{ + h8->per_regs[H8S_IO_TIOR0_L] = data; + h8s_tpu_x_write_tior( h8, 0); +} + +void h8s_tpu_1_write_tior( h83xx_state *h8, UINT8 data) +{ + h8->per_regs[H8S_IO_TIOR1] = data; + h8s_tpu_x_write_tior( h8, 1); +} + +void h8s_tpu_2_write_tior( h83xx_state *h8, UINT8 data) +{ + h8->per_regs[H8S_IO_TIOR2] = data; + h8s_tpu_x_write_tior( h8, 2); +} + +void h8s_tpu_3_write_tior_h( h83xx_state *h8, UINT8 data) +{ + h8->per_regs[H8S_IO_TIOR3_H] = data; + h8s_tpu_x_write_tior( h8, 3); +} + +void h8s_tpu_3_write_tior_l( h83xx_state *h8, UINT8 data) +{ + h8->per_regs[H8S_IO_TIOR3_L] = data; + h8s_tpu_x_write_tior( h8, 3); +} + +void h8s_tpu_4_write_tior( h83xx_state *h8, UINT8 data) +{ + h8->per_regs[H8S_IO_TIOR4] = data; + h8s_tpu_x_write_tior( h8, 4); +} + +void h8s_tpu_5_write_tior( h83xx_state *h8, UINT8 data) +{ + h8->per_regs[H8S_IO_TIOR5] = data; + h8s_tpu_x_write_tior( h8, 5); +} + +void h8s_tpu_write_tstr( h83xx_state *h8, UINT8 data) +{ + const int tpu_max = (h8->device->type() == H8S2323) ? 6 : 3; + UINT8 old_data = h8->per_regs[H8S_IO_TSTR]; + int i; + h8->per_regs[H8S_IO_TSTR] = data; + for (i = 0; i < tpu_max; i++) + { + if ((data & (1 << i)) != (old_data & (1 << i))) + { + if ((data & (1 << i)) != 0) + { + h8s_tpu_x_start( h8, i); + } + else + { + h8s_tpu_x_stop( h8, i); + } + } + } +} + +static TIMER_CALLBACK( h8s_tpu_callback) +{ + h83xx_state *h8 = (h83xx_state *)ptr; + h8s_tpu_x_callback( h8, param); +} + +///////////////////////////////// +// SERIAL CONTROLLER INTERFACE // +///////////////////////////////// + +typedef struct +{ + UINT32 reg_smr, reg_brr, reg_scr, reg_tdr, reg_ssr, reg_rdr; + UINT32 reg_pdr, reg_port; + UINT8 port_mask_sck, port_mask_txd, port_mask_rxd; + UINT8 int_tx, int_rx; +} H8S_SCI_ENTRY; + +const H8S_SCI_ENTRY H8S_SCI_TABLE[] = +{ + // SCI 0 + { + H8S_IO_SMR0, H8S_IO_BRR0, H8S_IO_SCR0, H8S_IO_TDR0, H8S_IO_SSR0, H8S_IO_RDR0, + H8S_IO_P3DR, H8S_IO_PORT3, + H8S_P3_SCK0, H8S_P3_TXD0, H8S_P3_RXD0, + H8S_INT_TXI0, H8S_INT_RXI0 + }, + // SCI 1 + { + H8S_IO_SMR1, H8S_IO_BRR1, H8S_IO_SCR1, H8S_IO_TDR1, H8S_IO_SSR1, H8S_IO_RDR1, + H8S_IO_P3DR, H8S_IO_PORT3, + H8S_P3_SCK1, H8S_P3_TXD1, H8S_P3_RXD1, + H8S_INT_TXI1, H8S_INT_RXI1 + }, + // SCI 2 + { + H8S_IO_SMR2, H8S_IO_BRR2, H8S_IO_SCR2, H8S_IO_TDR2, H8S_IO_SSR2, H8S_IO_RDR2, + H8S_IO_P5DR, H8S_IO_PORT5, + H8S_P5_SCK2, H8S_P5_TXD2, H8S_P5_RXD2, + H8S_INT_TXI2, H8S_INT_RXI2 + } +}; + +const H8S_SCI_ENTRY *h8s_sci_entry( int num) +{ + return &H8S_SCI_TABLE[num]; +} + +void h8s_sci_init(h83xx_state *h8) +{ + int i; + for (i=0;i<3;i++) + { + h8->sci[i].timer = h8->device->machine().scheduler().timer_alloc(FUNC(h8s_sci_callback), h8); + h8->sci[i].timer->adjust(attotime::never, i); + } +} + +static TIMER_CALLBACK(h8s_sci_callback) +{ + h83xx_state *h8 = (h83xx_state *)ptr; + verboselog( h8->device->machine(), 7, "h8s_sci_callback (%d)\n", param); +} + +void h8s_sci_start(h83xx_state *h8, int num) +{ + #if 0 + h8->sci[num].timer->adjust(h8->sci[num].bitrate, num); + #endif +} + +void h8s_sci_stop(h83xx_state *h8, int num) +{ + h8->sci[num].timer->adjust(attotime::never, num); +} + +void h8s_sci_execute(h83xx_state *h8, int num) +{ + UINT8 scr, tdr, ssr, rdr, tsr, rsr, pdr, port; + int i; + const H8S_SCI_ENTRY *info = h8s_sci_entry( num); + verboselog( h8->device->machine(), 5, "h8s_sci_execute(%d)\n", num); + // load regs + scr = h8->per_regs[info->reg_scr]; + tdr = h8->per_regs[info->reg_tdr]; + ssr = h8->per_regs[info->reg_ssr]; + rdr = h8->per_regs[info->reg_rdr]; + tsr = 0; + rsr = 0; + pdr = h8->per_regs[info->reg_pdr] & (~info->port_mask_sck); + // move byte from TDR to TSR + if (scr & H8S_SCR_TE) + { + tsr = tdr; + ssr |= H8S_SSR_TDRE; + } + // generate transmit data empty interrupt + if ((scr & H8S_SCR_TIE) && (ssr & H8S_SSR_TDRE)) h8s2xxx_interrupt_request(h8, info->int_tx); + // transmit/receive bits + for (i=0;i<8;i++) + { + // write bit + if (scr & H8S_SCR_TE) + { + if (tsr & (1 << i)) pdr = pdr | info->port_mask_txd; else pdr = pdr & (~info->port_mask_txd); + h8->io->write_byte( H8S_IO_ADDR( info->reg_pdr), pdr); + } + // clock high to low + h8->io->write_byte( H8S_IO_ADDR( info->reg_pdr), pdr | info->port_mask_sck); + h8->io->write_byte( H8S_IO_ADDR( info->reg_pdr), pdr); + // read bit + if (scr & H8S_SCR_RE) + { + port = h8->io->read_byte(H8S_IO_ADDR( info->reg_port)); + if (port & info->port_mask_rxd) rsr = rsr | (1 << i); + } + } + // move byte from RSR to RDR + if (scr & H8S_SCR_RE) + { + rdr = rsr; + //ssr |= H8S_SSR_RDRF; + } + // generate receive data full interrupt + if ((scr & H8S_SCR_RIE) && (ssr & H8S_SSR_RDRF)) h8s2xxx_interrupt_request(h8, info->int_rx); + // save regs + h8->per_regs[info->reg_scr] = scr; + h8->per_regs[info->reg_tdr] = tdr; + h8->per_regs[info->reg_ssr] = ssr; + h8->per_regs[info->reg_rdr] = rdr; +} + +const double SCR_CKE[] = { 0.5, 2, 8, 32 }; // = 2 ^ ((2 * cke) - 1) +const int SMR_MODE[] = { 64, 8 }; + +void h8s_sci_rate(h83xx_state *h8, int num) +{ + UINT8 brr, scr, smr, cke, mode; + UINT32 bitrate; + const H8S_SCI_ENTRY *info = h8s_sci_entry( num); + // read regs + brr = h8->per_regs[info->reg_brr]; + scr = h8->per_regs[info->reg_scr]; + smr = h8->per_regs[info->reg_smr]; + verboselog( h8->device->machine(), 2, "BRR %02X SCR %02X SMR %02X\n", brr, scr, smr); + // calculate bitrate + cke = (scr >> 0) & 3; + mode = (smr >> 7) & 1; + bitrate = (UINT32)((h8->device->unscaled_clock() / (brr + 1)) / (SMR_MODE[mode] * SCR_CKE[cke])); + verboselog( h8->device->machine(), 2, "SCI%d bitrate %d\n", num, bitrate); + // store bitrate + h8->sci[num].bitrate = bitrate; +} + +//////////////////////////// +// INTERNAL I/O REGISTERS // +//////////////////////////// + +void h8s_onchip_reg_write_8(h83xx_state *h8, int offset, UINT8 data) +{ + verboselog( h8->device->machine(), 9, "%08X | %08X <- %02X\n", h8->ppc, H8S_IO_ADDR(offset), data); + switch (offset) + { + // SCI 0 + case H8S_IO_SSR0 : h8->per_regs[offset] = data; if ((data & H8S_SSR_TDRE) == 0) h8s_sci_execute(h8, 0); break; + case H8S_IO_SCR0 : h8->per_regs[offset] = data; if (data & H8S_SCR_TIE) h8s2xxx_interrupt_request(h8, h8s_sci_entry(0)->int_tx); break; + case H8S_IO_BRR0 : h8->per_regs[offset] = data; h8s_sci_rate(h8, 0); h8s_sci_start(h8, 0); break; + // SCI 1 + case H8S_IO_SSR1 : h8->per_regs[offset] = data; if ((data & H8S_SSR_TDRE) == 0) h8s_sci_execute(h8, 1); break; + case H8S_IO_SCR1 : h8->per_regs[offset] = data; if (data & H8S_SCR_RIE) h8s2xxx_interrupt_request(h8, h8s_sci_entry(1)->int_rx); break; + case H8S_IO_BRR1 : h8->per_regs[offset] = data; h8s_sci_rate(h8, 1); h8s_sci_start(h8, 1); break; + // SCI 2 + case H8S_IO_SSR2 : h8->per_regs[offset] = data; if ((data & H8S_SSR_TDRE) == 0) h8s_sci_execute(h8, 2); break; + case H8S_IO_SCR2 : h8->per_regs[offset] = data; if (data & H8S_SCR_TIE) h8s2xxx_interrupt_request(h8, h8s_sci_entry(2)->int_tx); break; + case H8S_IO_BRR2 : h8->per_regs[offset] = data; h8s_sci_rate(h8, 2); h8s_sci_start(h8, 2); break; + // TMR 0 + case H8S_IO_TCR0 : h8s_tmr_x_write_tcr( h8, 0, data); break; + case H8S_IO_TCNT0 : h8s_tmr_x_write_tcnt( h8, 0, data); break; + case H8S_IO_TCORA0 : h8s_tmr_x_write_tcora( h8, 0, data); break; + case H8S_IO_TCORB0 : h8s_tmr_x_write_tcorb( h8, 0, data); break; + // TMR 1 + case H8S_IO_TCR1 : h8s_tmr_x_write_tcr( h8, 1, data); break; + case H8S_IO_TCNT1 : h8s_tmr_x_write_tcnt( h8, 1, data); break; + case H8S_IO_TCORA1 : h8s_tmr_x_write_tcora( h8, 1, data); break; + case H8S_IO_TCORB1 : h8s_tmr_x_write_tcorb( h8, 1, data); break; + // ports + case H8S_IO_P1DR : case H8S_IO_P2DR : case H8S_IO_P3DR : case H8S_IO_P4DR : case H8S_IO_P5DR : + case H8S_IO_PADR : case H8S_IO_PBDR : case H8S_IO_PCDR : case H8S_IO_PDDR : case H8S_IO_PEDR : + case H8S_IO_PFDR : h8->per_regs[offset] = data; h8->io->write_byte( H8S_IO_ADDR( offset), data); break; + // ... + case H8S_IO_PFDDR : h8->per_regs[offset] = data; h8->io->write_byte( H8S_IO_ADDR( offset), data); break; + // TPU + case H8S_IO_TSTR : h8s_tpu_write_tstr( h8, data); break; + // DMA + case H8S_IO_DMABCRL : + { + h8->per_regs[offset] = data; + if (h8->device->type() == H8S2323) + { + if ((data & 0x40) && (data & 0x80)) + { + UINT32 i, dma_src, dma_dst; + UINT16 dma_cnt, dma_con; + int sz; + dma_src = h8->program->read_dword( H8S_IO_ADDR(H8S_IO_MAR1AH)); + dma_dst = h8->program->read_dword( H8S_IO_ADDR(H8S_IO_MAR1BH)); + dma_cnt = h8->program->read_word( H8S_IO_ADDR(H8S_IO_ETCR1A)); + dma_con = h8->program->read_word( H8S_IO_ADDR(H8S_IO_DMACR1A)); + sz = (dma_con & 0x8000) ? 2 : 1; + for (i=0;i<dma_cnt;i++) + { + if (dma_con & 0x8000) h8->program->write_word( dma_dst, h8->program->read_word( dma_src)); else h8->program->write_byte( dma_dst, h8->program->read_byte( dma_src)); + if (dma_con & 0x2000) { if (dma_con & 0x4000) dma_src -= sz; else dma_src += sz; } + if (dma_con & 0x0020) { if (dma_con & 0x0040) dma_dst -= sz; else dma_dst += sz; } + } + h8->per_regs[H8S_IO_DMABCRL] &= ~0x40; + } + } + } + break; + // ... + default : + { + h8->per_regs[offset] = data; + } + break; + } +} + +void h8s_onchip_reg_write_16(h83xx_state *h8, int offset, UINT16 data) +{ + verboselog( h8->device->machine(), 9, "%08X | %08X <- %04X\n", h8->ppc, H8S_IO_ADDR(offset), data); + switch (offset) + { + // TPU 0 + case H8S_IO_TCNT0_H : h8s_tpu_x_write_tcnt( h8, 0, data); break; + case H8S_IO_TGR0A_H : h8s_tpu_x_write_tgra( h8, 0, data); break; + case H8S_IO_TGR0B_H : h8s_tpu_x_write_tgrb( h8, 0, data); break; + case H8S_IO_TGR0C_H : h8s_tpu_x_write_tgrc( h8, 0, data); break; + case H8S_IO_TGR0D_H : h8s_tpu_x_write_tgrd( h8, 0, data); break; + // TPU 1 + case H8S_IO_TCNT1_H : h8s_tpu_x_write_tcnt( h8, 1, data); break; + case H8S_IO_TGR1A_H : h8s_tpu_x_write_tgra( h8, 1, data); break; + case H8S_IO_TGR1B_H : h8s_tpu_x_write_tgrb( h8, 1, data); break; + // TPU 2 + case H8S_IO_TCNT2_H : h8s_tpu_x_write_tcnt( h8, 2, data); break; + case H8S_IO_TGR2A_H : h8s_tpu_x_write_tgra( h8, 2, data); break; + case H8S_IO_TGR2B_H : h8s_tpu_x_write_tgrb( h8, 2, data); break; + // TPU 3 + case H8S_IO_TCNT3_H : if (h8->device->type() == H8S2323) h8s_tpu_x_write_tcnt( h8, 3, data); break; + case H8S_IO_TGR3A_H : if (h8->device->type() == H8S2323) h8s_tpu_x_write_tgra( h8, 3, data); break; + case H8S_IO_TGR3B_H : if (h8->device->type() == H8S2323) h8s_tpu_x_write_tgrb( h8, 3, data); break; + case H8S_IO_TGR3C_H : if (h8->device->type() == H8S2323) h8s_tpu_x_write_tgrc( h8, 3, data); break; + case H8S_IO_TGR3D_H : if (h8->device->type() == H8S2323) h8s_tpu_x_write_tgrd( h8, 3, data); break; + // TPU 4 + case H8S_IO_TCNT4_H : if (h8->device->type() == H8S2323) h8s_tpu_x_write_tcnt( h8, 4, data); break; + case H8S_IO_TGR4A_H : if (h8->device->type() == H8S2323) h8s_tpu_x_write_tgra( h8, 4, data); break; + case H8S_IO_TGR4B_H : if (h8->device->type() == H8S2323) h8s_tpu_x_write_tgrb( h8, 4, data); break; + // TPU 5 + case H8S_IO_TCNT5_H : if (h8->device->type() == H8S2323) h8s_tpu_x_write_tcnt( h8, 5, data); break; + case H8S_IO_TGR5A_H : if (h8->device->type() == H8S2323) h8s_tpu_x_write_tgra( h8, 5, data); break; + case H8S_IO_TGR5B_H : if (h8->device->type() == H8S2323) h8s_tpu_x_write_tgrb( h8, 5, data); break; + // ... + default : + { + h8s_onchip_reg_write_8( h8, offset + 0, (data >> 8) & 0xFF); + h8s_onchip_reg_write_8( h8, offset + 1, (data >> 0) & 0xFF); + } + break; + } +} + +UINT8 h8s_onchip_reg_read_8(h83xx_state *h8, int offset) +{ + UINT8 data; + switch (offset) + { + // SCI 0 + case H8S_IO_SSR0 : data = H8S_SSR_TDRE | H8S_SSR_TEND; break; + case H8S_IO_RDR0 : data = h8->io->read_byte( H8S_IO_ADDR( offset)); break; + // SCI 1 + case H8S_IO_SSR1 : data = H8S_SSR_TDRE | H8S_SSR_TEND; break; + // SCI 2 + case H8S_IO_SSR2 : + { + data = h8->per_regs[offset]; + if (!(h8->per_regs[H8S_IO_SCR2] & H8S_SCR_TE)) data |= H8S_SSR_TDRE; + } + break; + // ports + case H8S_IO_PORT1 : case H8S_IO_PORT2 : case H8S_IO_PORT3 : case H8S_IO_PORT4 : case H8S_IO_PORT5 : + case H8S_IO_PORTA : case H8S_IO_PORTB : case H8S_IO_PORTC : case H8S_IO_PORTD : case H8S_IO_PORTE : + case H8S_IO_PORTF : data = h8->io->read_byte( H8S_IO_ADDR( offset)); break; + // ... + case H8S_IO_P3DR : data = 0; break; // todo: without this cybiko hangs + // TMR 0 + case H8S_IO_TCNT0 : data = h8s_tmr_x_read_tcnt( h8, 0); break; + // TMR 1 + case H8S_IO_TCNT1 : data = h8s_tmr_x_read_tcnt( h8, 1); break; + // ... + // default + default : data = h8->per_regs[offset]; break; + } + verboselog( h8->device->machine(), 9, "%08X | %08X -> %02X\n", h8->ppc, H8S_IO_ADDR(offset), data); + return data; +} + +UINT16 h8s_onchip_reg_read_16(h83xx_state *h8, int offset) +{ + UINT16 data = 0; + switch (offset) + { + case H8S_IO_TCNT0_H : data = h8s_tpu_x_read_tcnt( h8, 0); break; + case H8S_IO_TCNT1_H : data = h8s_tpu_x_read_tcnt( h8, 1); break; + case H8S_IO_TCNT2_H : data = h8s_tpu_x_read_tcnt( h8, 2); break; + case H8S_IO_TCNT3_H : if (h8->device->type() == H8S2323) data = h8s_tpu_x_read_tcnt( h8, 3); break; + case H8S_IO_TCNT4_H : if (h8->device->type() == H8S2323) data = h8s_tpu_x_read_tcnt( h8, 4); break; + case H8S_IO_TCNT5_H : if (h8->device->type() == H8S2323) data = h8s_tpu_x_read_tcnt( h8, 5); break; + default : + { + UINT8 b[2]; + b[0] = h8s_onchip_reg_read_8( h8, offset + 0); + b[1] = h8s_onchip_reg_read_8( h8, offset + 1); + data = (b[0] << 8) | (b[1] << 0); + } + break; + } + verboselog( h8->device->machine(), 9, "%08X | %08X -> %04X\n", h8->ppc, H8S_IO_ADDR(offset), data); + return data; +} + +void h8s2241_per_regs_write_8(h83xx_state *h8, int offset, UINT8 data) +{ + h8s_onchip_reg_write_8(h8, offset, data); +} + +UINT8 h8s2241_per_regs_read_8(h83xx_state *h8, int offset) +{ + return h8s_onchip_reg_read_8(h8, offset); +} + +void h8s2241_per_regs_write_16(h83xx_state *h8, int offset, UINT16 data) +{ + h8s_onchip_reg_write_16(h8, offset, data); +} + +UINT16 h8s2241_per_regs_read_16(h83xx_state *h8, int offset) +{ + return h8s_onchip_reg_read_16(h8, offset); +} + +void h8s2246_per_regs_write_8(h83xx_state *h8, int offset, UINT8 data) +{ + h8s_onchip_reg_write_8(h8, offset, data); +} + +UINT8 h8s2246_per_regs_read_8(h83xx_state *h8, int offset) +{ + return h8s_onchip_reg_read_8(h8, offset); +} + +void h8s2246_per_regs_write_16(h83xx_state *h8, int offset, UINT16 data) +{ + h8s_onchip_reg_write_16(h8, offset, data); +} + +UINT16 h8s2246_per_regs_read_16(h83xx_state *h8, int offset) +{ + return h8s_onchip_reg_read_16(h8, offset); +} + +void h8s2323_per_regs_write_8(h83xx_state *h8, int offset, UINT8 data) +{ + h8s_onchip_reg_write_8(h8, offset, data); +} + +UINT8 h8s2323_per_regs_read_8(h83xx_state *h8, int offset) +{ + return h8s_onchip_reg_read_8(h8, offset); +} + +void h8s2323_per_regs_write_16(h83xx_state *h8, int offset, UINT16 data) +{ + h8s_onchip_reg_write_16(h8, offset, data); +} + +UINT16 h8s2323_per_regs_read_16(h83xx_state *h8, int offset) +{ + return h8s_onchip_reg_read_16(h8, offset); +} |