summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/avr8/avr8.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/avr8/avr8.cpp')
-rw-r--r--src/devices/cpu/avr8/avr8.cpp4296
1 files changed, 2306 insertions, 1990 deletions
diff --git a/src/devices/cpu/avr8/avr8.cpp b/src/devices/cpu/avr8/avr8.cpp
index de75492ee7d..49f3728c1b5 100644
--- a/src/devices/cpu/avr8/avr8.cpp
+++ b/src/devices/cpu/avr8/avr8.cpp
@@ -12,7 +12,7 @@
the existing opcodes has been shown to wildly corrupt the video output in Craft, so one can assume that the
existing timing is 100% correct.
- Unimplemented opcodes: SPM, SPM Z+, SLEEP, BREAK, WDR, EICALL, JMP, CALL
+ Unimplemented opcodes: SPM, SPM Z+, SLEEP, BREAK, WDR, EICALL
- Changelist -
05 Jul. 2015 [Felipe Sanches]
@@ -60,91 +60,72 @@
#include "emu.h"
#include "avr8.h"
#include "avr8dasm.h"
-#include "debugger.h"
-
-#define LOG_UNKNOWN (1 << 1)
-#define LOG_BOOT (1 << 2)
-#define LOG_TIMER0 (1 << 3)
-#define LOG_TIMER1 (1 << 4)
-#define LOG_TIMER2 (1 << 5)
-#define LOG_TIMER3 (1 << 6)
-#define LOG_TIMER4 (1 << 7)
-#define LOG_TIMER5 (1 << 8)
-#define LOG_TIMER0_TICK (1 << 9)
-#define LOG_TIMER1_TICK (1 << 10)
-#define LOG_TIMER2_TICK (1 << 11)
-#define LOG_TIMER3_TICK (1 << 12)
-#define LOG_TIMER4_TICK (1 << 13)
-#define LOG_TIMER5_TICK (1 << 14)
-#define LOG_EEPROM (1 << 15)
-#define LOG_GPIO (1 << 16)
-#define LOG_WDOG (1 << 17)
-#define LOG_CLOCK (1 << 18)
-#define LOG_POWER (1 << 19)
-#define LOG_OSC (1 << 20)
-#define LOG_PINCHG (1 << 21)
-#define LOG_EXTMEM (1 << 22)
-#define LOG_ADC (1 << 23)
-#define LOG_DIGINPUT (1 << 24)
-#define LOG_ASYNC (1 << 25)
-#define LOG_TWI (1 << 26)
-#define LOG_UART (1 << 27)
+
+#define LOG_UNKNOWN (1U << 1)
+#define LOG_BOOT (1U << 2)
+#define LOG_TIMER0 (1U << 3)
+#define LOG_TIMER1 (1U << 4)
+#define LOG_TIMER2 (1U << 5)
+#define LOG_TIMER3 (1U << 6)
+#define LOG_TIMER4 (1U << 7)
+#define LOG_TIMER5 (1U << 8)
+#define LOG_TIMER0_TICK (1U << 9)
+#define LOG_TIMER1_TICK (1U << 10)
+#define LOG_TIMER2_TICK (1U << 11)
+#define LOG_TIMER3_TICK (1U << 12)
+#define LOG_TIMER4_TICK (1U << 13)
+#define LOG_TIMER5_TICK (1U << 14)
+#define LOG_EEPROM (1U << 15)
+#define LOG_GPIO (1U << 16)
+#define LOG_WDOG (1U << 17)
+#define LOG_CLOCK (1U << 18)
+#define LOG_POWER (1U << 19)
+#define LOG_OSC (1U << 20)
+#define LOG_PINCHG (1U << 21)
+#define LOG_EXTMEM (1U << 22)
+#define LOG_ADC (1U << 23)
+#define LOG_DIGINPUT (1U << 24)
+#define LOG_ASYNC (1U << 25)
+#define LOG_TWI (1U << 26)
+#define LOG_UART (1U << 27)
#define LOG_TIMERS (LOG_TIMER0 | LOG_TIMER1 | LOG_TIMER2 | LOG_TIMER3 | LOG_TIMER4 | LOG_TIMER5)
#define LOG_TIMER_TICKS (LOG_TIMER0_TICK | LOG_TIMER1_TICK | LOG_TIMER2_TICK | LOG_TIMER3_TICK | LOG_TIMER4_TICK | LOG_TIMER5_TICK)
-#define LOG_ALL (LOG_UNKNOWN | LOG_BOOT | LOG_TIMERS | LOG_TIMER_TICKS | LOG_EEPROM | LOG_GPIO | LOG_WDOG | LOG_CLOCK | LOG_POWER \
+#define LOG_ALL (LOG_UNKNOWN | LOG_BOOT | LOG_TIMERS | LOG_EEPROM | LOG_GPIO | LOG_WDOG | LOG_CLOCK | LOG_POWER \
| LOG_OSC | LOG_PINCHG | LOG_EXTMEM | LOG_ADC | LOG_DIGINPUT | LOG_ASYNC | LOG_TWI | LOG_UART)
#define VERBOSE (0)
+//#define LOG_OUTPUT_FUNC osd_printf_info
#include "logmacro.h"
+
//**************************************************************************
// ENUMS AND MACROS
//**************************************************************************
enum
{
- AVR8_SREG_C = 0,
- AVR8_SREG_Z,
- AVR8_SREG_N,
- AVR8_SREG_V,
- AVR8_SREG_S,
- AVR8_SREG_H,
- AVR8_SREG_T,
- AVR8_SREG_I,
-
- AVR8_SREG_MASK_C = 0x01,
- AVR8_SREG_MASK_Z = 0x02,
- AVR8_SREG_MASK_N = 0x04,
- AVR8_SREG_MASK_V = 0x08,
- AVR8_SREG_MASK_S = 0x10,
- AVR8_SREG_MASK_H = 0x20,
- AVR8_SREG_MASK_T = 0x40,
- AVR8_SREG_MASK_I = 0x80
+ SREG_C = 0,
+ SREG_Z,
+ SREG_N,
+ SREG_V,
+ SREG_S,
+ SREG_H,
+ SREG_T,
+ SREG_I,
+
+ SREG_MASK_C = 0x01,
+ SREG_MASK_Z = 0x02,
+ SREG_MASK_N = 0x04,
+ SREG_MASK_V = 0x08,
+ SREG_MASK_S = 0x10,
+ SREG_MASK_H = 0x20,
+ SREG_MASK_T = 0x40,
+ SREG_MASK_I = 0x80
};
// I/O Enums
enum
{
- WGM1_NORMAL = 0,
- WGM1_PWM_8_PC,
- WGM1_PWM_9_PC,
- WGM1_PWM_10_PC,
- WGM1_CTC_OCR,
- WGM1_FAST_PWM_8,
- WGM1_FAST_PWM_9,
- WGM1_FAST_PWM_10,
- WGM1_PWM_PFC_ICR,
- WGM1_PWM_PFC_OCR,
- WGM1_PWM_PC_ICR,
- WGM1_PWM_PC_OCR,
- WGM1_CTC_ICR,
- WGM1_RESERVED,
- WGM1_FAST_PWM_ICR,
- WGM1_FAST_PWM_OCR
-};
-
-enum
-{
WGM02_NORMAL = 0,
WGM02_PWM_PC,
WGM02_CTC_CMP,
@@ -195,13 +176,6 @@ enum
WGM5_FAST_PWM_OCR
};
-static const char avr8_reg_name[4] = { 'A', 'B', 'C', 'D' };
-
-#define SREG_R(b) ((m_r[AVR8_REGIDX_SREG] & (1 << (b))) >> (b))
-#define SREG_W(b,v) m_r[AVR8_REGIDX_SREG] = (m_r[AVR8_REGIDX_SREG] & ~(1 << (b))) | ((v) << (b))
-#define SREG m_r[AVR8_REGIDX_SREG]
-#define NOT(x) (1 - (x))
-
// Opcode-Parsing Defines
#define RD2(op) (((op) >> 4) & 0x0003)
#define RD3(op) (((op) >> 4) & 0x0007)
@@ -224,369 +198,332 @@ static const char avr8_reg_name[4] = { 'A', 'B', 'C', 'D' };
#define XREG ((m_r[27] << 8) | m_r[26])
#define YREG ((m_r[29] << 8) | m_r[28])
#define ZREG ((m_r[31] << 8) | m_r[30])
-#define SPREG ((m_r[AVR8_REGIDX_SPH] << 8) | m_r[AVR8_REGIDX_SPL])
+#define SPREG ((m_r[SPH] << 8) | m_r[SPL])
// I/O Defines
-#define AVR8_OCR1CH (m_r[AVR8_REGIDX_OCR1CH])
-#define AVR8_OCR1CL (m_r[AVR8_REGIDX_OCR1CL])
-#define AVR8_OCR1BH (m_r[AVR8_REGIDX_OCR1BH])
-#define AVR8_OCR1BL (m_r[AVR8_REGIDX_OCR1BL])
-#define AVR8_OCR1AH (m_r[AVR8_REGIDX_OCR1AH])
-#define AVR8_OCR1AL (m_r[AVR8_REGIDX_OCR1AL])
-#define AVR8_ICR1H (m_r[AVR8_REGIDX_ICR1H])
-#define AVR8_ICR1L (m_r[AVR8_REGIDX_ICR1L])
-#define AVR8_TCNT1H (m_r[AVR8_REGIDX_TCNT1H])
-#define AVR8_TCNT1L (m_r[AVR8_REGIDX_TCNT1L])
-
-#define AVR8_OCR3CH (m_r[AVR8_REGIDX_OCR3CH])
-#define AVR8_OCR3CL (m_r[AVR8_REGIDX_OCR3CL])
-#define AVR8_OCR3BH (m_r[AVR8_REGIDX_OCR3BH])
-#define AVR8_OCR3BL (m_r[AVR8_REGIDX_OCR3BL])
-#define AVR8_OCR3AH (m_r[AVR8_REGIDX_OCR3AH])
-#define AVR8_OCR3AL (m_r[AVR8_REGIDX_OCR3AL])
-#define AVR8_ICR3H (m_r[AVR8_REGIDX_ICR3H])
-#define AVR8_ICR3L (m_r[AVR8_REGIDX_ICR3L])
-#define AVR8_TCNT3H (m_r[AVR8_REGIDX_TCNT3H])
-#define AVR8_TCNT3L (m_r[AVR8_REGIDX_TCNT3L])
-
-#define AVR8_OCR4CH (m_r[AVR8_REGIDX_OCR4CH])
-#define AVR8_OCR4CL (m_r[AVR8_REGIDX_OCR4CL])
-#define AVR8_OCR4BH (m_r[AVR8_REGIDX_OCR4BH])
-#define AVR8_OCR4BL (m_r[AVR8_REGIDX_OCR4BL])
-#define AVR8_OCR4AH (m_r[AVR8_REGIDX_OCR4AH])
-#define AVR8_OCR4AL (m_r[AVR8_REGIDX_OCR4AL])
-#define AVR8_ICR4H (m_r[AVR8_REGIDX_ICR4H])
-#define AVR8_ICR4L (m_r[AVR8_REGIDX_ICR4L])
-#define AVR8_TCNT4H (m_r[AVR8_REGIDX_TCNT4H])
-#define AVR8_TCNT4L (m_r[AVR8_REGIDX_TCNT4L])
-
-#define AVR8_OCR5CH (m_r[AVR8_REGIDX_OCR5CH])
-#define AVR8_OCR5CL (m_r[AVR8_REGIDX_OCR5CL])
-#define AVR8_OCR5BH (m_r[AVR8_REGIDX_OCR5BH])
-#define AVR8_OCR5BL (m_r[AVR8_REGIDX_OCR5BL])
-#define AVR8_OCR5AH (m_r[AVR8_REGIDX_OCR5AH])
-#define AVR8_OCR5AL (m_r[AVR8_REGIDX_OCR5AL])
-#define AVR8_ICR5H (m_r[AVR8_REGIDX_ICR5H])
-#define AVR8_ICR5L (m_r[AVR8_REGIDX_ICR5L])
-#define AVR8_TCNT5H (m_r[AVR8_REGIDX_TCNT5H])
-#define AVR8_TCNT5L (m_r[AVR8_REGIDX_TCNT5L])
-
-#define AVR8_TCCR0B (m_r[AVR8_REGIDX_TCCR0B])
-#define AVR8_TCCR0B_FOC0A_MASK 0x80
-#define AVR8_TCCR0B_FOC0A_SHIFT 7
-#define AVR8_TCCR0B_FOC0B_MASK 0x40
-#define AVR8_TCCR0B_FOC0B_SHIFT 6
-#define AVR8_TCCR0B_WGM0_2_MASK 0x08
-#define AVR8_TCCR0B_WGM0_2_SHIFT 3
-#define AVR8_TCCR0B_CS_MASK 0x07
-#define AVR8_TCCR0B_CS_SHIFT 0
-#define AVR8_TIMER0_CLOCK_SELECT (AVR8_TCCR0B & AVR8_TCCR0B_CS_MASK)
-
-#define AVR8_TCCR0A (m_r[AVR8_REGIDX_TCCR0A])
-#define AVR8_TCCR0A_COM0A_MASK 0xc0
-#define AVR8_TCCR0A_COM0A_SHIFT 6
-#define AVR8_TCCR0A_COM0B_MASK 0x30
-#define AVR8_TCCR0A_COM0B_SHIFT 4
-#define AVR8_TCCR0A_WGM0_10_MASK 0x03
-#define AVR8_TCCR0A_WGM0_10_SHIFT 0
-#define AVR8_TCCR0A_COM0A ((AVR8_TCCR0A & AVR8_TCCR0A_COM0A_MASK) >> AVR8_TCCR0A_COM0A_SHIFT)
-#define AVR8_TCCR0A_COM0B ((AVR8_TCCR0A & AVR8_TCCR0A_COM0B_MASK) >> AVR8_TCCR0A_COM0B_SHIFT)
-#define AVR8_TCCR0A_WGM0_10 (AVR8_TCCR0A & AVR8_TCCR0A_WGM0_10_MASK)
-
-#define AVR8_TIMSK0 (m_r[AVR8_REGIDX_TIMSK0])
-#define AVR8_TIMSK0_OCIE0B_MASK 0x04
-#define AVR8_TIMSK0_OCIE0A_MASK 0x02
-#define AVR8_TIMSK0_TOIE0_MASK 0x01
-#define AVR8_TIMSK0_OCIE0B ((AVR8_TIMSK0 & AVR8_TIMSK0_OCIE0B_MASK) >> 2)
-#define AVR8_TIMSK0_OCIE0A ((AVR8_TIMSK0 & AVR8_TIMSK0_OCIE0A_MASK) >> 1)
-#define AVR8_TIMSK0_TOIE0 (AVR8_TIMSK0 & AVR8_TIMSK0_TOIE0_MASK)
-
-#define AVR8_TIFR0 (m_r[AVR8_REGIDX_TIFR0])
-#define AVR8_TIFR0_OCF0B_MASK 0x04
-#define AVR8_TIFR0_OCF0B_SHIFT 2
-#define AVR8_TIFR0_OCF0A_MASK 0x02
-#define AVR8_TIFR0_OCF0A_SHIFT 1
-#define AVR8_TIFR0_TOV0_MASK 0x01
-#define AVR8_TIFR0_TOV0_SHIFT 0
-#define AVR8_TIFR0_MASK (AVR8_TIFR0_TOV0_MASK | AVR8_TIFR0_OCF0B_MASK | AVR8_TIFR0_OCF0A_MASK)
-
-#define AVR8_TCCR1B (m_r[AVR8_REGIDX_TCCR1B])
-#define AVR8_TCCR1B_ICNC1_MASK 0x80
-#define AVR8_TCCR1B_ICNC1_SHIFT 7
-#define AVR8_TCCR1B_ICES1_MASK 0x40
-#define AVR8_TCCR1B_ICES1_SHIFT 6
-#define AVR8_TCCR1B_WGM1_32_MASK 0x18
-#define AVR8_TCCR1B_WGM1_32_SHIFT 3
-#define AVR8_TCCR1B_CS_MASK 0x07
-#define AVR8_TCCR1B_CS_SHIFT 0
-#define AVR8_TIMER1_CLOCK_SELECT (AVR8_TCCR1B & AVR8_TCCR1B_CS_MASK)
-
-#define AVR8_TCCR1A (m_r[AVR8_REGIDX_TCCR1A])
-#define AVR8_TCCR1A_COM1A_MASK 0xc0
-#define AVR8_TCCR1A_COM1A_SHIFT 6
-#define AVR8_TCCR1A_COM1B_MASK 0x30
-#define AVR8_TCCR1A_COM1B_SHIFT 4
-#define AVR8_TCCR1A_WGM1_10_MASK 0x03
-#define AVR8_TCCR1A_WGM1_10_SHIFT 0
-#define AVR8_TCCR1A_COM1A ((AVR8_TCCR1A & AVR8_TCCR1A_COM1A_MASK) >> AVR8_TCCR1A_COM1A_SHIFT)
-#define AVR8_TCCR1A_COM1B ((AVR8_TCCR1A & AVR8_TCCR1A_COM1B_MASK) >> AVR8_TCCR1A_COM1B_SHIFT)
-#define AVR8_TCCR1A_WGM1_10 (AVR8_TCCR1A & AVR8_TCCR1A_WGM1_10_MASK)
-
-#define AVR8_TIMSK1 (m_r[AVR8_REGIDX_TIMSK1])
-#define AVR8_TIMSK1_ICIE1_MASK 0x20
-#define AVR8_TIMSK1_OCIE1B_MASK 0x04
-#define AVR8_TIMSK1_OCIE1A_MASK 0x02
-#define AVR8_TIMSK1_TOIE1_MASK 0x01
-#define AVR8_TIMSK1_ICIE1 ((AVR8_TIMSK1 & AVR8_TIMSK1_ICIE1_MASK) >> 5)
-#define AVR8_TIMSK1_OCIE1B ((AVR8_TIMSK1 & AVR8_TIMSK1_OCIE1B_MASK) >> 2)
-#define AVR8_TIMSK1_OCIE1A ((AVR8_TIMSK1 & AVR8_TIMSK1_OCIE1A_MASK) >> 1)
-#define AVR8_TIMSK1_TOIE1 (AVR8_TIMSK1 & AVR8_TIMSK1_TOIE1_MASK)
-
-#define AVR8_TIFR1 (m_r[AVR8_REGIDX_TIFR1])
-#define AVR8_TIFR1_ICF1_MASK 0x20
-#define AVR8_TIFR1_ICF1_SHIFT 5
-#define AVR8_TIFR1_OCF1B_MASK 0x04
-#define AVR8_TIFR1_OCF1B_SHIFT 2
-#define AVR8_TIFR1_OCF1A_MASK 0x02
-#define AVR8_TIFR1_OCF1A_SHIFT 1
-#define AVR8_TIFR1_TOV1_MASK 0x01
-#define AVR8_TIFR1_TOV1_SHIFT 0
-#define AVR8_TIFR1_MASK (AVR8_TIFR1_ICF1_MASK | AVR8_TIFR1_TOV1_MASK | \
- AVR8_TIFR1_OCF1B_MASK | AVR8_TIFR1_OCF1A_MASK)
-
-#define AVR8_TCCR2B (m_r[AVR8_REGIDX_TCCR2B])
-#define AVR8_TCCR2B_FOC2A_MASK 0x80
-#define AVR8_TCCR2B_FOC2A_SHIFT 7
-#define AVR8_TCCR2B_FOC2B_MASK 0x40
-#define AVR8_TCCR2B_FOC2B_SHIFT 6
-#define AVR8_TCCR2B_WGM2_2_MASK 0x08
-#define AVR8_TCCR2B_WGM2_2_SHIFT 3
-#define AVR8_TCCR2B_CS_MASK 0x07
-#define AVR8_TCCR2B_CS_SHIFT 0
-#define AVR8_TIMER2_CLOCK_SELECT (AVR8_TCCR2B & AVR8_TCCR2B_CS_MASK)
-
-#define AVR8_TCCR2A (m_r[AVR8_REGIDX_TCCR2A])
-#define AVR8_TCCR2A_COM2A_MASK 0xc0
-#define AVR8_TCCR2A_COM2A_SHIFT 6
-#define AVR8_TCCR2A_COM2B_MASK 0x30
-#define AVR8_TCCR2A_COM2B_SHIFT 4
-#define AVR8_TCCR2A_WGM2_10_MASK 0x03
-#define AVR8_TCCR2A_WGM2_10_SHIFT 0
-#define AVR8_TCCR2A_COM2A ((AVR8_TCCR2A & AVR8_TCCR2A_COM2A_MASK) >> AVR8_TCCR2A_COM2A_SHIFT)
-#define AVR8_TCCR2A_COM2B ((AVR8_TCCR2A & AVR8_TCCR2A_COM2B_MASK) >> AVR8_TCCR2A_COM2B_SHIFT)
-#define AVR8_TCCR2A_WGM2_10 (AVR8_TCCR2A & AVR8_TCCR2A_WGM2_10_MASK)
-
-#define AVR8_TIMSK2 (m_r[AVR8_REGIDX_TIMSK2])
-#define AVR8_TIMSK2_OCIE2B_MASK 0x04
-#define AVR8_TIMSK2_OCIE2A_MASK 0x02
-#define AVR8_TIMSK2_TOIE2_MASK 0x01
-#define AVR8_TIMSK2_OCIE2B ((AVR8_TIMSK2 & AVR8_TIMSK2_OCIE2B_MASK) >> 2)
-#define AVR8_TIMSK2_OCIE2A ((AVR8_TIMSK2 & AVR8_TIMSK2_OCIE2A_MASK) >> 1)
-#define AVR8_TIMSK2_TOIE2 (AVR8_TIMSK2 & AVR8_TIMSK2_TOIE2_MASK)
-
-#define AVR8_TIFR2 (m_r[AVR8_REGIDX_TIFR2])
-#define AVR8_TIFR2_OCF2B_MASK 0x04
-#define AVR8_TIFR2_OCF2B_SHIFT 2
-#define AVR8_TIFR2_OCF2A_MASK 0x02
-#define AVR8_TIFR2_OCF2A_SHIFT 1
-#define AVR8_TIFR2_TOV2_MASK 0x01
-#define AVR8_TIFR2_TOV2_SHIFT 0
-#define AVR8_TIFR2_MASK (AVR8_TIFR2_TOV2_MASK | AVR8_TIFR2_OCF2B_MASK | AVR8_TIFR2_OCF2A_MASK)
-
-#define AVR8_TIMSK3 (m_r[AVR8_REGIDX_TIMSK3])
-#define AVR8_TIMSK3_OCIE3C_MASK 0x08
-#define AVR8_TIMSK3_OCIE3B_MASK 0x04
-#define AVR8_TIMSK3_OCIE3A_MASK 0x02
-#define AVR8_TIMSK3_TOIE3_MASK 0x01
-#define AVR8_TIMSK3_OCIE3C ((AVR8_TIMSK3 & AVR8_TIMSK3_OCIE3C_MASK) >> 3)
-#define AVR8_TIMSK3_OCIE3B ((AVR8_TIMSK3 & AVR8_TIMSK3_OCIE3B_MASK) >> 2)
-#define AVR8_TIMSK3_OCIE3A ((AVR8_TIMSK3 & AVR8_TIMSK3_OCIE3A_MASK) >> 1)
-#define AVR8_TIMSK3_TOIE3 ((AVR8_TIMSK3 & AVR8_TIMSK3_TOIE3_MASK) >> 0)
-
-#define AVR8_TCCR4C (m_r[AVR8_REGIDX_TCCR4C])
-
-#define AVR8_TCCR4B (m_r[AVR8_REGIDX_TCCR4B])
-#define AVR8_TCCR4B_FOC4A_MASK 0x80
-#define AVR8_TCCR4B_FOC4A_SHIFT 7
-#define AVR8_TCCR4B_FOC4B_MASK 0x40
-#define AVR8_TCCR4B_FOC4B_SHIFT 6
-#define AVR8_TCCR4B_FOC4C_MASK 0x20
-#define AVR8_TCCR4B_FOC4C_SHIFT 5
-#define AVR8_TCCR4B_WGM4_32_MASK 0x18
-#define AVR8_TCCR4B_WGM4_32_SHIFT 3
-#define AVR8_TCCR4B_CS_MASK 0x07
-#define AVR8_TCCR4B_CS_SHIFT 0
-#define AVR8_TIMER4_CLOCK_SELECT ((AVR8_TCCR4B & AVR8_TCCR4B_CS_MASK) >> AVR8_TCCR4B_CS_SHIFT)
-
-#define AVR8_TCCR4A (m_r[AVR8_REGIDX_TCCR4A])
-#define AVR8_TCCR4A_COM4A_MASK 0xc0
-#define AVR8_TCCR4A_COM4A_SHIFT 6
-#define AVR8_TCCR4A_COM4B_MASK 0x30
-#define AVR8_TCCR4A_COM4B_SHIFT 4
-#define AVR8_TCCR4A_COM4C_MASK 0x0c
-#define AVR8_TCCR4A_COM4C_SHIFT 2
-#define AVR8_TCCR4A_WGM4_10_MASK 0x03
-#define AVR8_TCCR4A_WGM4_10_SHIFT 0
-#define AVR8_TCCR4A_COM4A ((AVR8_TCCR4A & AVR8_TCCR4A_COM4A_MASK) >> AVR8_TCCR4A_COM4A_SHIFT)
-#define AVR8_TCCR4A_COM4B ((AVR8_TCCR4A & AVR8_TCCR4A_COM4B_MASK) >> AVR8_TCCR4A_COM4B_SHIFT)
-#define AVR8_TCCR4A_COM4C ((AVR8_TCCR4A & AVR8_TCCR4A_COM4C_MASK) >> AVR8_TCCR4A_COM4C_SHIFT)
-#define AVR8_TCCR4A_WGM2_10 (AVR8_TCCR4A & AVR8_TCCR4A_WGM2_10_MASK)
-
-#define AVR8_WGM4_32 ((AVR8_TCCR4B & AVR8_TCCR4B_WGM4_32_MASK) >> AVR8_TCCR4B_WGM4_32_SHIFT)
-#define AVR8_WGM4_10 ((AVR8_TCCR4A & AVR8_TCCR4A_WGM4_10_MASK) >> AVR8_TCCR4A_WGM4_10_SHIFT)
-#define AVR8_WGM4 ((AVR8_WGM4_32 << 2) | AVR8_WGM4_10)
-
-#define AVR8_TIMSK4 (m_r[AVR8_REGIDX_TIMSK4])
-#define AVR8_TIMSK4_OCIE4B_MASK 0x04
-#define AVR8_TIMSK4_OCIE4A_MASK 0x02
-#define AVR8_TIMSK4_TOIE4_MASK 0x01
-#define AVR8_TIMSK4_OCIE4B ((AVR8_TIMSK4 & AVR8_TIMSK4_OCIE4B_MASK) >> 2)
-#define AVR8_TIMSK4_OCIE4A ((AVR8_TIMSK4 & AVR8_TIMSK4_OCIE4A_MASK) >> 1)
-#define AVR8_TIMSK4_TOIE4 (AVR8_TIMSK4 & AVR8_TIMSK4_TOIE4_MASK)
-
-#define AVR8_TIFR4 (m_r[AVR8_REGIDX_TIFR4])
-#define AVR8_TIFR4_OCF4B_MASK 0x04
-#define AVR8_TIFR4_OCF4B_SHIFT 2
-#define AVR8_TIFR4_OCF4A_MASK 0x02
-#define AVR8_TIFR4_OCF4A_SHIFT 1
-#define AVR8_TIFR4_TOV4_MASK 0x01
-#define AVR8_TIFR4_TOV4_SHIFT 0
-#define AVR8_TIFR4_MASK (AVR8_TIFR4_TOV4_MASK | AVR8_TIFR4_OCF4B_MASK | AVR8_TIFR4_OCF4A_MASK)
+#define TCCR0B_CS_SHIFT 0
+#define TCCR0B_CS_MASK 0x07
+#define TCCR0B_WGM0_2_SHIFT 3
+#define TCCR0B_WGM0_2_MASK 0x08
+#define TCCR0B_FOC0B_SHIFT 6
+#define TCCR0B_FOC0B_MASK 0x40
+#define TCCR0B_FOC0A_SHIFT 7
+#define TCCR0B_FOC0A_MASK 0x80
+#define TIMER0_CLOCK_SELECT (m_r[TCCR0B] & TCCR0B_CS_MASK)
+
+#define TCCR0A_WGM0_10_SHIFT 0
+#define TCCR0A_WGM0_10_MASK 0x03
+#define TCCR0A_COM0B_SHIFT 4
+#define TCCR0A_COM0B_MASK 0x30
+#define TCCR0A_COM0A_SHIFT 6
+#define TCCR0A_COM0A_MASK 0xc0
+#define TCCR0A_COM0A ((m_r[TCCR0A] & TCCR0A_COM0A_MASK) >> TCCR0A_COM0A_SHIFT)
+#define TCCR0A_COM0B ((m_r[TCCR0A] & TCCR0A_COM0B_MASK) >> TCCR0A_COM0B_SHIFT)
+#define TCCR0A_WGM0_10 (m_r[TCCR0A] & TCCR0A_WGM0_10_MASK)
+
+#define TIMSK0_TOIE0_BIT 0
+#define TIMSK0_OCIE0A_BIT 1
+#define TIMSK0_OCIE0B_BIT 2
+#define TIMSK0_TOIE0_MASK (1 << TIMSK0_TOIE0_BIT)
+#define TIMSK0_OCIE0A_MASK (1 << TIMSK0_OCIE0A_BIT)
+#define TIMSK0_OCIE0B_MASK (1 << TIMSK0_OCIE0B_BIT)
+#define TIMSK0_TOIE0 (BIT(m_r[TIMSK0], TIMSK0_TOIE0_BIT))
+#define TIMSK0_OCIE0A (BIT(m_r[TIMSK0], TIMSK0_OCIE0A_BIT))
+#define TIMSK0_OCIE0B (BIT(m_r[TIMSK0], TIMSK0_OCIE0B_BIT))
+
+#define TIFR0_TOV0_SHIFT 0
+#define TIFR0_TOV0_MASK 0x01
+#define TIFR0_OCF0A_SHIFT 1
+#define TIFR0_OCF0A_MASK 0x02
+#define TIFR0_OCF0B_SHIFT 2
+#define TIFR0_OCF0B_MASK 0x04
+#define TIFR0_MASK (TIFR0_TOV0_MASK | TIFR0_OCF0B_MASK | TIFR0_OCF0A_MASK)
+
+#define TCCR1B_CS_SHIFT 0
+#define TCCR1B_CS_MASK 0x07
+#define TCCR1B_WGM1_32_SHIFT 3
+#define TCCR1B_WGM1_32_MASK 0x18
+#define TCCR1B_ICES1_SHIFT 6
+#define TCCR1B_ICES1_MASK 0x40
+#define TCCR1B_ICNC1_SHIFT 7
+#define TCCR1B_ICNC1_MASK 0x80
+#define TIMER1_CLOCK_SELECT (m_r[TCCR1B] & TCCR1B_CS_MASK)
+
+#define TCCR1A_WGM1_10_SHIFT 0
+#define TCCR1A_WGM1_10_MASK 0x03
+#define TCCR1A_COM1AB_SHIFT 4
+#define TCCR1A_COM1AB_MASK 0xf0
+#define TCCR1A_COM1B_SHIFT 4
+#define TCCR1A_COM1B_MASK 0x30
+#define TCCR1A_COM1A_SHIFT 6
+#define TCCR1A_COM1A_MASK 0xc0
+#define TCCR1A_COM1A ((m_r[TCCR1A] & TCCR1A_COM1A_MASK) >> TCCR1A_COM1A_SHIFT)
+#define TCCR1A_COM1B ((m_r[TCCR1A] & TCCR1A_COM1B_MASK) >> TCCR1A_COM1B_SHIFT)
+#define TCCR1A_WGM1_10 (m_r[TCCR1A] & TCCR1A_WGM1_10_MASK)
+
+#define TIMSK1_TOIE1_BIT 0
+#define TIMSK1_OCIE1A_BIT 1
+#define TIMSK1_OCIE1B_BIT 2
+#define TIMSK1_ICIE1_BIT 5
+#define TIMSK1_TOIE1_MASK (1 << TIMSK1_TOIE1_BIT)
+#define TIMSK1_OCIE1A_MASK (1 << TIMSK1_OCIE1A_BIT)
+#define TIMSK1_OCIE1B_MASK (1 << TIMSK1_OCIE1B_BIT)
+#define TIMSK1_ICIE1_MASK (1 << TIMSK1_ICIE1_BIT)
+#define TIMSK1_TOIE1 (BIT(m_r[TIMSK1], TIMSK1_TOIE1_BIT))
+#define TIMSK1_OCIE1A (BIT(m_r[TIMSK1], TIMSK1_OCIE1A_BIT))
+#define TIMSK1_OCIE1B (BIT(m_r[TIMSK1], TIMSK1_OCIE1B_BIT))
+#define TIMSK1_ICIE1 (BIT(m_r[TIMSK1], TIMSK1_ICIE1_BIT))
+
+#define TIFR1_TOV1_SHIFT 0
+#define TIFR1_TOV1_MASK 0x01
+#define TIFR1_OCF1A_SHIFT 1
+#define TIFR1_OCF1A_MASK 0x02
+#define TIFR1_OCF1B_SHIFT 2
+#define TIFR1_OCF1B_MASK 0x04
+#define TIFR1_ICF1_SHIFT 5
+#define TIFR1_ICF1_MASK 0x20
+#define TIFR1_MASK (TIFR1_ICF1_MASK | TIFR1_TOV1_MASK | TIFR1_OCF1B_MASK | TIFR1_OCF1A_MASK)
+
+#define TCCR2B_CS_SHIFT 0
+#define TCCR2B_CS_MASK 0x07
+#define TCCR2B_WGM2_2_SHIFT 3
+#define TCCR2B_WGM2_2_MASK 0x08
+#define TCCR2B_FOC2B_SHIFT 6
+#define TCCR2B_FOC2B_MASK 0x40
+#define TCCR2B_FOC2A_SHIFT 7
+#define TCCR2B_FOC2A_MASK 0x80
+#define TIMER2_CLOCK_SELECT (m_r[TCCR2B] & TCCR2B_CS_MASK)
+
+#define TCCR2A_WGM2_10_SHIFT 0
+#define TCCR2A_WGM2_10_MASK 0x03
+#define TCCR2A_COM2B_SHIFT 4
+#define TCCR2A_COM2B_MASK 0x30
+#define TCCR2A_COM2A_SHIFT 6
+#define TCCR2A_COM2A_MASK 0xc0
+#define TCCR2A_COM2A ((m_r[TCCR2A] & TCCR2A_COM2A_MASK) >> TCCR2A_COM2A_SHIFT)
+#define TCCR2A_COM2B ((m_r[TCCR2A] & TCCR2A_COM2B_MASK) >> TCCR2A_COM2B_SHIFT)
+#define TCCR2A_WGM2_10 (m_r[TCCR2A] & TCCR2A_WGM2_10_MASK)
+
+#define TIMSK2_TOIE2_BIT 0
+#define TIMSK2_OCIE2A_BIT 1
+#define TIMSK2_OCIE2B_BIT 2
+#define TIMSK2_TOIE2_MASK (1 << TIMSK2_TOIE2_BIT)
+#define TIMSK2_OCIE2A_MASK (1 << TIMSK2_OCIE2A_BIT)
+#define TIMSK2_OCIE2B_MASK (1 << TIMSK2_OCIE2B_BIT)
+#define TIMSK2_TOIE2 (BIT(m_r[TIMSK2], TIMSK2_TOIE2_BIT))
+#define TIMSK2_OCIE2A (BIT(m_r[TIMSK2], TIMSK2_OCIE2A_BIT))
+#define TIMSK2_OCIE2B (BIT(m_r[TIMSK2], TIMSK2_OCIE2B_BIT))
+
+#define TIFR2_TOV2_SHIFT 0
+#define TIFR2_TOV2_MASK 0x01
+#define TIFR2_OCF2A_SHIFT 1
+#define TIFR2_OCF2A_MASK 0x02
+#define TIFR2_OCF2B_SHIFT 2
+#define TIFR2_OCF2B_MASK 0x04
+#define TIFR2_MASK (TIFR2_TOV2_MASK | TIFR2_OCF2B_MASK | TIFR2_OCF2A_MASK)
+
+#define TIMSK3_TOIE3_BIT 0
+#define TIMSK3_OCIE3A_BIT 1
+#define TIMSK3_OCIE3B_BIT 2
+#define TIMSK3_OCIE3C_BIT 3
+#define TIMSK3_TOIE3 (BIT(m_r[TIMSK3], TIMSK3_TOIE3_BIT))
+#define TIMSK3_OCIE3A (BIT(m_r[TIMSK3], TIMSK3_OCIE3A_BIT))
+#define TIMSK3_OCIE3B (BIT(m_r[TIMSK3], TIMSK3_OCIE3B_BIT))
+#define TIMSK3_OCIE3C (BIT(m_r[TIMSK3], TIMSK3_OCIE3C_BIT))
+
+#define TCCR4B_CS_SHIFT 0
+#define TCCR4B_CS_MASK 0x07
+#define TCCR4B_WGM4_32_SHIFT 3
+#define TCCR4B_WGM4_32_MASK 0x18
+#define TCCR4B_FOC4C_SHIFT 5
+#define TCCR4B_FOC4C_MASK 0x20
+#define TCCR4B_FOC4B_SHIFT 6
+#define TCCR4B_FOC4B_MASK 0x40
+#define TCCR4B_FOC4A_SHIFT 7
+#define TCCR4B_FOC4A_MASK 0x80
+#define TIMER4_CLOCK_SELECT ((m_r[TCCR4B] & TCCR4B_CS_MASK) >> TCCR4B_CS_SHIFT)
+
+#define TCCR4A_WGM4_10_SHIFT 0
+#define TCCR4A_WGM4_10_MASK 0x03
+#define TCCR4A_COM4C_SHIFT 2
+#define TCCR4A_COM4C_MASK 0x0c
+#define TCCR4A_COM4B_SHIFT 4
+#define TCCR4A_COM4B_MASK 0x30
+#define TCCR4A_COM4A_SHIFT 6
+#define TCCR4A_COM4A_MASK 0xc0
+#define TCCR4A_COM4A ((m_r[TCCR4A] & TCCR4A_COM4A_MASK) >> TCCR4A_COM4A_SHIFT)
+#define TCCR4A_COM4B ((m_r[TCCR4A] & TCCR4A_COM4B_MASK) >> TCCR4A_COM4B_SHIFT)
+#define TCCR4A_COM4C ((m_r[TCCR4A] & TCCR4A_COM4C_MASK) >> TCCR4A_COM4C_SHIFT)
+#define TCCR4A_WGM2_10 (m_r[TCCR4A] & TCCR4A_WGM2_10_MASK)
+
+#define WGM4_32 ((m_r[TCCR4B] & TCCR4B_WGM4_32_MASK) >> TCCR4B_WGM4_32_SHIFT)
+#define WGM4_10 ((m_r[TCCR4A] & TCCR4A_WGM4_10_MASK) >> TCCR4A_WGM4_10_SHIFT)
+#define WGM4 ((WGM4_32 << 2) | WGM4_10)
+
+#define TIMSK4_TOIE4_BIT 0
+#define TIMSK4_OCIE4A_BIT 1
+#define TIMSK4_OCIE4B_BIT 2
+#define TIMSK4_TOIE4 (BIT(m_r[TIMSK4], TIMSK4_TOIE4_BIT))
+#define TIMSK4_OCIE4A (BIT(m_r[TIMSK4], TIMSK4_OCIE4A_BIT))
+#define TIMSK4_OCIE4B (BIT(m_r[TIMSK4], TIMSK4_OCIE4B_BIT))
+
+#define TIFR4_TOV4_SHIFT 0
+#define TIFR4_TOV4_MASK 0x01
+#define TIFR4_OCF4A_SHIFT 1
+#define TIFR4_OCF4A_MASK 0x02
+#define TIFR4_OCF4B_SHIFT 2
+#define TIFR4_OCF4B_MASK 0x04
+#define TIFR4_MASK (TIFR4_TOV4_MASK | TIFR4_OCF4B_MASK | TIFR4_OCF4A_MASK)
+
+#define TCCR5C_FOC5C_SHIFT 5
+#define TCCR5C_FOC5C_MASK 0x20
+#define TCCR5C_FOC5B_SHIFT 6
+#define TCCR5C_FOC5B_MASK 0x40
+#define TCCR5C_FOC5A_SHIFT 7
+#define TCCR5C_FOC5A_MASK 0x80
+
+#define TCCR5B_CS_SHIFT 0
+#define TCCR5B_CS_MASK 0x07
+#define TCCR5B_WGM5_32_SHIFT 3
+#define TCCR5B_WGM5_32_MASK 0x18
+#define TCCR5B_ICES5_SHIFT 6
+#define TCCR5B_ICES5_MASK 0x40
+#define TCCR5B_ICNC5_SHIFT 7
+#define TCCR5B_ICNC5_MASK 0x80
+#define TIMER5_CLOCK_SELECT ((m_r[TCCR5B] & TCCR5B_CS_MASK) >> TCCR5B_CS_SHIFT)
+
+#define TCCR5A_WGM5_10_SHIFT 0
+#define TCCR5A_WGM5_10_MASK 0x03
+#define TCCR5A_COM5C_SHIFT 2
+#define TCCR5A_COM5C_MASK 0x0c
+#define TCCR5A_COM5B_SHIFT 4
+#define TCCR5A_COM5B_MASK 0x30
+#define TCCR5A_COM5A_SHIFT 6
+#define TCCR5A_COM5A_MASK 0xc0
+#define TCCR5A_COM5A ((m_r[TCCR5A] & TCCR5A_COM5A_MASK) >> TCCR5A_COM5A_SHIFT)
+#define TCCR5A_COM5B ((m_r[TCCR5A] & TCCR5A_COM5B_MASK) >> TCCR5A_COM5B_SHIFT)
+#define TCCR5A_COM5C ((m_r[TCCR5A] & TCCR5A_COM5C_MASK) >> TCCR5A_COM5C_SHIFT)
+#define TCCR5A_WGM5_10 (m_r[TCCR5A] & TCCR5A_WGM5_10_MASK)
+
+#define WGM5_32 ((m_r[TCCR5B] & TCCR5B_WGM5_32_MASK) >> TCCR5B_WGM5_32_SHIFT)
+#define WGM5_10 ((m_r[TCCR5A] & TCCR5A_WGM5_10_MASK) >> TCCR5A_WGM5_10_SHIFT)
+#define WGM5 ((WGM5_32 << 2) | WGM5_10)
+
+#define TIMSK5_TOIE5_BIT 0
+#define TIMSK5_OCIE5A_BIT 1
+#define TIMSK5_OCIE5B_BIT 2
+#define TIMSK5_OCIE5C_BIT 3
+#define TIMSK5_ICIE5_BIT 5
+#define TIMSK5_TOIE5_MASK (1 << TIMSK5_TOIE5_BIT)
+#define TIMSK5_OCIE5A_MASK (1 << TIMSK5_OCIE5A_BIT)
+#define TIMSK5_OCIE5B_MASK (1 << TIMSK5_OCIE5B_BIT)
+#define TIMSK5_OCIE5C_MASK (1 << TIMSK5_OCIE5C_BIT)
+#define TIMSK5_ICIE5_MASK (1 << TIMSK5_ICIE5_BIT)
+#define TIMSK5_TOIE5 (BIT(m_r[TIMSK5], TIMSK5_TOIE5_BIT))
+#define TIMSK5_OCIE5A (BIT(m_r[TIMSK5], TIMSK5_OCIE5A_BIT))
+#define TIMSK5_OCIE5B (BIT(m_r[TIMSK5], TIMSK5_OCIE5B_BIT))
+#define TIMSK5_OCIE5C (BIT(m_r[TIMSK5], TIMSK5_OCIE5C_BIT))
+#define TIMSK5_ICIE5C (BIT(m_r[TIMSK5], TIMSK5_ICIE5C_BIT))
+
+#define TIFR5_ICF5_MASK 0x20
+#define TIFR5_ICF5_SHIFT 5
+#define TIFR5_OCF5C_MASK 0x08
+#define TIFR5_OCF5C_SHIFT 3
+#define TIFR5_OCF5B_MASK 0x04
+#define TIFR5_OCF5B_SHIFT 2
+#define TIFR5_OCF5A_MASK 0x02
+#define TIFR5_OCF5A_SHIFT 1
+#define TIFR5_TOV5_MASK 0x01
+#define TIFR5_TOV5_SHIFT 0
+#define TIFR5_MASK (TIFR5_ICF5_MASK | TIFR5_OCF5C_MASK | TIFR5_OCF5B_MASK | TIFR5_OCF5A_MASK | TIFR5_TOV5_MASK)
+#define TIFR5_ICF5 ((m_r[TIFR5] & TIFR5_ICF5_MASK) >> TIFR5_ICF5_SHIFT)
+#define TIFR5_OCF5C ((m_r[TIFR5] & TIFR5_OCF5C_MASK) >> TIFR5_OCF5C_SHIFT)
+#define TIFR5_OCF5B ((m_r[TIFR5] & TIFR5_OCF5B_MASK) >> TIFR5_OCF5B_SHIFT)
+#define TIFR5_OCF5A ((m_r[TIFR5] & TIFR5_OCF5A_MASK) >> TIFR5_OCF5A_SHIFT)
+#define TIFR5_TOV5 ((m_r[TIFR5] & TIFR5_TOV5_MASK) >> TIFR5_TOV5_SHIFT)
//---------------------------------------------------------------
-#define AVR8_TCCR5C (m_r[AVR8_REGIDX_TCCR5C])
-#define AVR8_TCCR5C_FOC5A_MASK 0x80
-#define AVR8_TCCR5C_FOC5A_SHIFT 7
-#define AVR8_TCCR5C_FOC5B_MASK 0x40
-#define AVR8_TCCR5C_FOC5B_SHIFT 6
-#define AVR8_TCCR5C_FOC5C_MASK 0x20
-#define AVR8_TCCR5C_FOC5C_SHIFT 5
-
-#define AVR8_TCCR5B (m_r[AVR8_REGIDX_TCCR5B])
-#define AVR8_TCCR5B_ICNC5_MASK 0x80
-#define AVR8_TCCR5B_ICNC5_SHIFT 7
-#define AVR8_TCCR5B_ICES5_MASK 0x40
-#define AVR8_TCCR5B_ICES5_SHIFT 6
-#define AVR8_TCCR5B_WGM5_32_MASK 0x18
-#define AVR8_TCCR5B_WGM5_32_SHIFT 3
-#define AVR8_TCCR5B_CS_MASK 0x07
-#define AVR8_TCCR5B_CS_SHIFT 0
-#define AVR8_TIMER5_CLOCK_SELECT ((AVR8_TCCR5B & AVR8_TCCR5B_CS_MASK) >> AVR8_TCCR5B_CS_SHIFT)
-
-#define AVR8_TCCR5A (m_r[AVR8_REGIDX_TCCR4A])
-#define AVR8_TCCR5A_COM5A_MASK 0xc0
-#define AVR8_TCCR5A_COM5A_SHIFT 6
-#define AVR8_TCCR5A_COM5B_MASK 0x30
-#define AVR8_TCCR5A_COM5B_SHIFT 4
-#define AVR8_TCCR5A_COM5C_MASK 0x0c
-#define AVR8_TCCR5A_COM5C_SHIFT 2
-#define AVR8_TCCR5A_WGM5_10_MASK 0x03
-#define AVR8_TCCR5A_WGM5_10_SHIFT 0
-#define AVR8_TCCR5A_COM5A ((AVR8_TCCR5A & AVR8_TCCR5A_COM5A_MASK) >> AVR8_TCCR5A_COM5A_SHIFT)
-#define AVR8_TCCR5A_COM5B ((AVR8_TCCR5A & AVR8_TCCR5A_COM5B_MASK) >> AVR8_TCCR5A_COM5B_SHIFT)
-#define AVR8_TCCR5A_COM5C ((AVR8_TCCR5A & AVR8_TCCR5A_COM5C_MASK) >> AVR8_TCCR5A_COM5C_SHIFT)
-#define AVR8_TCCR5A_WGM5_10 (AVR8_TCCR5A & AVR8_TCCR5A_WGM5_10_MASK)
-
-#define AVR8_WGM5_32 ((AVR8_TCCR5B & AVR8_TCCR5B_WGM5_32_MASK) >> AVR8_TCCR5B_WGM5_32_SHIFT)
-#define AVR8_WGM5_10 ((AVR8_TCCR5A & AVR8_TCCR5A_WGM5_10_MASK) >> AVR8_TCCR5A_WGM5_10_SHIFT)
-#define AVR8_WGM5 ((AVR8_WGM5_32 << 2) | AVR8_WGM5_10)
-
-#define AVR8_TIMSK5 (m_r[AVR8_REGIDX_TIMSK5])
-#define AVR8_TIMSK5_ICIE5_MASK 0x20
-#define AVR8_TIMSK5_OCIE5C_MASK 0x08
-#define AVR8_TIMSK5_OCIE5B_MASK 0x04
-#define AVR8_TIMSK5_OCIE5A_MASK 0x02
-#define AVR8_TIMSK5_TOIE5_MASK 0x01
-
-#define AVR8_TIMSK5_ICIE5C ((AVR8_TIMSK5 & AVR8_TIMSK5_ICIE5C_MASK) >> 5)
-#define AVR8_TIMSK5_OCIE5C ((AVR8_TIMSK5 & AVR8_TIMSK5_OCIE5C_MASK) >> 3)
-#define AVR8_TIMSK5_OCIE5B ((AVR8_TIMSK5 & AVR8_TIMSK5_OCIE5B_MASK) >> 2)
-#define AVR8_TIMSK5_OCIE5A ((AVR8_TIMSK5 & AVR8_TIMSK5_OCIE5A_MASK) >> 1)
-#define AVR8_TIMSK5_TOIE5 (AVR8_TIMSK5 & AVR8_TIMSK5_TOIE5_MASK)
-
-#define AVR8_TIFR5 (m_r[AVR8_REGIDX_TIFR5])
-#define AVR8_TIFR5_ICF5_MASK 0x20
-#define AVR8_TIFR5_ICF5_SHIFT 5
-#define AVR8_TIFR5_OCF5C_MASK 0x08
-#define AVR8_TIFR5_OCF5C_SHIFT 3
-#define AVR8_TIFR5_OCF5B_MASK 0x04
-#define AVR8_TIFR5_OCF5B_SHIFT 2
-#define AVR8_TIFR5_OCF5A_MASK 0x02
-#define AVR8_TIFR5_OCF5A_SHIFT 1
-#define AVR8_TIFR5_TOV5_MASK 0x01
-#define AVR8_TIFR5_TOV5_SHIFT 0
-#define AVR8_TIFR5_MASK (AVR8_TIFR5_ICF5_MASK | AVR8_TIFR5_OCF5C_MASK | AVR8_TIFR5_OCF5B_MASK | AVR8_TIFR5_OCF5A_MASK | AVR8_TIFR5_TOV5_MASK)
-
-
-#define AVR8_TIFR5_ICF5 ((AVR8_TIFR5 & AVR8_TIFR5_ICF5_MASK) >> AVR8_TIFR5_ICF5_SHIFT)
-#define AVR8_TIFR5_OCF5C ((AVR8_TIFR5 & AVR8_TIFR5_OCF5C_MASK) >> AVR8_TIFR5_OCF5C_SHIFT)
-#define AVR8_TIFR5_OCF5B ((AVR8_TIFR5 & AVR8_TIFR5_OCF5B_MASK) >> AVR8_TIFR5_OCF5B_SHIFT)
-#define AVR8_TIFR5_OCF5A ((AVR8_TIFR5 & AVR8_TIFR5_OCF5A_MASK) >> AVR8_TIFR5_OCF5A_SHIFT)
-#define AVR8_TIFR5_TOV5 ((AVR8_TIFR5 & AVR8_TIFR5_TOV5_MASK) >> AVR8_TIFR5_TOV5_SHIFT)
+
+#define WGM0 (((m_r[TCCR0B] & 0x08) >> 1) | (m_r[TCCR0A] & 0x03))
+
+#define OCR1A ((m_r[OCR1AH] << 8) | m_r[OCR1AL])
+#define OCR1B ((m_r[OCR1BH] << 8) | m_r[OCR1BL])
+#define OCR1C ((m_r[OCR1CH] << 8) | m_r[OCR1CL])
+#define ICR1 ((m_r[ICR1H] << 8) | m_r[ICR1L])
+#define WGM1 (((m_r[TCCR1B] & 0x18) >> 1) | (m_r[TCCR1A] & 0x03))
+
+#define WGM2 (((m_r[TCCR2B] & 0x08) >> 1) | (m_r[TCCR2A] & 0x03))
+
+#define ICR3 ((m_r[ICR3H] << 8) | m_r[ICR3L])
+#define OCR3A ((m_r[OCR3AH] << 8) | m_r[OCR3AL])
+
+#define ICR4 ((m_r[ICR4H] << 8) | m_r[ICR4L])
+#define OCR4A ((m_r[OCR4AH] << 8) | m_r[OCR4AL])
+
+#define ICR5 ((m_r[ICR5H] << 8) | m_r[ICR5L])
+#define OCR5A ((m_r[OCR5AH] << 8) | m_r[OCR5AL])
+
+#define GTCCR_PSRASY_MASK 0x02
+#define GTCCR_PSRASY_SHIFT 1
+
+#define SPSR_SPR2X (m_r[SPSR] & SPSR_SPR2X_MASK)
+
+#define SPCR_SPIE ((m_r[SPCR] & SPCR_SPIE_MASK) >> 7)
+#define SPCR_SPE ((m_r[SPCR] & SPCR_SPE_MASK) >> 6)
+#define SPCR_DORD ((m_r[SPCR] & SPCR_DORD_MASK) >> 5)
+#define SPCR_MSTR ((m_r[SPCR] & SPCR_MSTR_MASK) >> 4)
+#define SPCR_CPOL ((m_r[SPCR] & SPCR_CPOL_MASK) >> 3)
+#define SPCR_CPHA ((m_r[SPCR] & SPCR_CPHA_MASK) >> 2)
+#define SPCR_SPR (m_r[SPCR] & SPCR_SPR_MASK)
+
+#define SPI_RATE ((SPSR_SPR2X << 2) | SPCR_SPR)
+
+#define PORTB_MOSI 0x08
+
+#define EECR_MASK 0x3f
+#define EECR_EERE_BIT 0
+#define EECR_EEPE_BIT 1
+#define EECR_EEMPE_BIT 2
+#define EECR_EERIE_BIT 3
+#define EECR_EEPM_BIT 4
+#define EECR_EERE_MASK (1 << EECR_EERE_BIT)
+#define EECR_EEPE_MASK (1 << EECR_EEPE_BIT)
+#define EECR_EEMPE_MASK (1 << EECR_EEMPE_BIT)
+#define EECR_EERIE_MASK (1 << EECR_EERIE_BIT)
+#define EECR_EEPM_MASK (3 << EECR_EEPM_BIT)
+#define EECR_EERE (BIT(m_r[EECR], EECR_EERE_BIT))
+#define EECR_EEPE (BIT(m_r[EECR], EECR_EEPE_BIT))
+#define EECR_EEMPE (BIT(m_r[EECR], EECR_EEMPE_BIT))
+#define EECR_EERIE (BIT(m_r[EECR], EECR_EERIE_BIT))
+#define EECR_EEPM ((m_r[EECR] & EECR_EEPM_MASK) >> EECR_EEPM_BIT)
//---------------------------------------------------------------
-#define AVR8_OCR0A m_r[AVR8_REGIDX_OCR0A]
-#define AVR8_OCR0B m_r[AVR8_REGIDX_OCR0B]
-#define AVR8_TCNT0 m_r[AVR8_REGIDX_TCNT0]
-#define AVR8_WGM0 (((AVR8_TCCR0B & 0x08) >> 1) | (AVR8_TCCR0A & 0x03))
-
-#define AVR8_OCR1A ((AVR8_OCR1AH << 8) | AVR8_OCR1AL)
-#define AVR8_OCR1B ((AVR8_OCR1BH << 8) | AVR8_OCR1BL)
-#define AVR8_OCR1C ((AVR8_OCR1CH << 8) | AVR8_OCR1CL)
-#define AVR8_ICR1 ((AVR8_ICR1H << 8) | AVR8_ICR1L)
-#define AVR8_TCNT1 ((AVR8_TCNT1H << 8) | AVR8_TCNT1L)
-#define AVR8_WGM1 (((AVR8_TCCR1B & 0x18) >> 1) | (AVR8_TCCR1A & 0x03))
-#define AVR8_TCNT1_DIR (state->m_tcnt1_direction)
-
-#define AVR8_OCR2A m_r[AVR8_REGIDX_OCR2A]
-#define AVR8_OCR2B m_r[AVR8_REGIDX_OCR2B]
-#define AVR8_TCNT2 m_r[AVR8_REGIDX_TCNT2]
-#define AVR8_WGM2 (((AVR8_TCCR2B & 0x08) >> 1) | (AVR8_TCCR2A & 0x03))
-
-#define AVR8_ICR3 ((AVR8_ICR3H << 8) | AVR8_ICR3L)
-#define AVR8_OCR3A ((AVR8_OCR3AH << 8) | AVR8_OCR3AL)
-
-#define AVR8_ICR4 ((AVR8_ICR4H << 8) | AVR8_ICR4L)
-#define AVR8_ICR4H (m_r[AVR8_REGIDX_ICR4H])
-#define AVR8_ICR4L (m_r[AVR8_REGIDX_ICR4L])
-#define AVR8_OCR4A ((AVR8_OCR4AH << 8) | AVR8_OCR4AL)
-#define AVR8_OCR4B m_r[AVR8_REGIDX_OCR4B]
-#define AVR8_TCNT4 m_r[AVR8_REGIDX_TCNT4]
-
-#define AVR8_ICR5 ((AVR8_ICR5H << 8) | AVR8_ICR5L)
-#define AVR8_OCR5A ((AVR8_OCR5AH << 8) | AVR8_OCR5AL)
-
-#define AVR8_GTCCR_PSRASY_MASK 0x02
-#define AVR8_GTCCR_PSRASY_SHIFT 1
-
-#define AVR8_SPSR (m_r[AVR8_REGIDX_SPSR])
-#define AVR8_SPSR_SPR2X (AVR8_SPSR & AVR8_SPSR_SPR2X_MASK)
-
-#define AVR8_SPCR (m_r[AVR8_REGIDX_SPCR])
-#define AVR8_SPCR_SPIE ((AVR8_SPCR & AVR8_SPCR_SPIE_MASK) >> 7)
-#define AVR8_SPCR_SPE ((AVR8_SPCR & AVR8_SPCR_SPE_MASK) >> 6)
-#define AVR8_SPCR_DORD ((AVR8_SPCR & AVR8_SPCR_DORD_MASK) >> 5)
-#define AVR8_SPCR_MSTR ((AVR8_SPCR & AVR8_SPCR_MSTR_MASK) >> 4)
-#define AVR8_SPCR_CPOL ((AVR8_SPCR & AVR8_SPCR_CPOL_MASK) >> 3)
-#define AVR8_SPCR_CPHA ((AVR8_SPCR & AVR8_SPCR_CPHA_MASK) >> 2)
-#define AVR8_SPCR_SPR (AVR8_SPCR & AVR8_SPCR_SPR_MASK)
-
-#define AVR8_SPI_RATE ((AVR8_SPSR_SPR2X << 2) | AVR8_SPCR_SPR)
-
-#define AVR8_PORTB_MOSI 0x08
-
-#define AVR8_EECR m_r[AVR8_REGIDX_EECR] & 0x3F; //bits 6 and 7 are reserved and will always read as zero
-#define AVR8_EECR_EEPM_MASK 0x30
-#define AVR8_EECR_EERIE_MASK 0x08
-#define AVR8_EECR_EEMPE_MASK 0x04
-#define AVR8_EECR_EEPE_MASK 0x02
-#define AVR8_EECR_EERE_MASK 0x01
-#define AVR8_EECR_EEPM ((AVR8_EECR & AVR8_EECR_EEPM_MASK) >> 4)
-#define AVR8_EECR_EERIE ((AVR8_EECR & AVR8_EECR_EERIE_MASK) >> 3)
-#define AVR8_EECR_EEMPE ((AVR8_EECR & AVR8_EECR_EEMPE_MASK) >> 2)
-#define AVR8_EECR_EEPE ((AVR8_EECR & AVR8_EECR_EEPE_MASK) >> 1)
-#define AVR8_EECR_EERE ((AVR8_EECR & AVR8_EECR_EERE_MASK) >> 0)
+#define ADMUX_MUX_MASK 0x0f
+#define ADMUX_ADLAR_MASK 0x20
+#define ADMUX_REFS_MASK 0xc0
+#define ADMUX_MUX ((m_r[ADMUX] & ADMUX_MUX_MASK) >> 0)
+#define ADMUX_ADLAR ((m_r[ADMUX] & ADMUX_ADLAR_MASK) >> 5)
+#define ADMUX_REFS ((m_r[ADMUX] & ADMUX_REFS_MASK) >> 6)
+
+#define ADCSRB_ACME_MASK 0x40
+#define ADCSRB_ADTS_MASK 0x07
+#define ADCSRB_ACME ((m_r[ADCSRB] & ADCSRB_ACME_MASK) >> 6)
+#define ADCSRB_ADTS ((m_r[ADCSRB] & ADCSRB_ADTS_MASK) >> 0)
+
+#define ADCSRA_ADPS_MASK 0x07
+#define ADCSRA_ADIE_MASK 0x08
+#define ADCSRA_ADIF_MASK 0x10
+#define ADCSRA_ADATE_MASK 0x20
+#define ADCSRA_ADSC_MASK 0x40
+#define ADCSRA_ADEN_MASK 0x80
+#define ADCSRA_ADPS (m_r[ADCSRA] & ADCSRA_ADPS_MASK)
+#define ADCSRA_ADIE ((m_r[ADCSRA] & ADCSRA_ADIE_MASK) >> 3)
+#define ADCSRA_ADIF ((m_r[ADCSRA] & ADCSRA_ADIF_MASK) >> 4)
+#define ADCSRA_ADATE ((m_r[ADCSRA] & ADCSRA_ADATE_MASK) >> 5)
+#define ADCSRA_ADSC ((m_r[ADCSRA] & ADCSRA_ADSC_MASK) >> 6)
+#define ADCSRA_ADEN ((m_r[ADCSRA] & ADCSRA_ADEN_MASK) >> 7)
+
//**************************************************************************
// DEVICE INTERFACE
@@ -604,39 +541,171 @@ DEFINE_DEVICE_TYPE(ATTINY15, attiny15_device, "attiny15", "Atmel ATtiny15"
// INTERNAL ADDRESS MAP
//**************************************************************************
+template <int NumTimers>
+void avr8_device<NumTimers>::base_internal_map(address_map &map)
+{
+ map(0x0000, 0x01ff).ram().share(m_r);
+ map(0x0020, 0x0020).r(FUNC(avr8_device::pin_r<0>));
+ map(0x0022, 0x0022).rw(FUNC(avr8_device::gpio_r<GPIOA>), FUNC(avr8_device::port_w<GPIOA>));
+ map(0x0023, 0x0023).r(FUNC(avr8_device::pin_r<1>));
+ map(0x0025, 0x0025).rw(FUNC(avr8_device::gpio_r<GPIOB>), FUNC(avr8_device::port_w<GPIOB>));
+ map(0x0026, 0x0026).r(FUNC(avr8_device::pin_r<2>));
+ map(0x0028, 0x0028).rw(FUNC(avr8_device::gpio_r<GPIOC>), FUNC(avr8_device::port_w<GPIOC>));
+ map(0x0029, 0x0029).r(FUNC(avr8_device::pin_r<3>));
+ map(0x002b, 0x002b).rw(FUNC(avr8_device::gpio_r<GPIOD>), FUNC(avr8_device::port_w<GPIOD>));
+ map(0x002c, 0x002c).r(FUNC(avr8_device::pin_r<4>));
+ map(0x002e, 0x002e).rw(FUNC(avr8_device::gpio_r<GPIOE>), FUNC(avr8_device::port_w<GPIOE>));
+ map(0x002f, 0x002f).r(FUNC(avr8_device::pin_r<5>));
+ map(0x0031, 0x0031).rw(FUNC(avr8_device::gpio_r<GPIOF>), FUNC(avr8_device::port_w<GPIOF>));
+ map(0x0032, 0x0032).r(FUNC(avr8_device::pin_r<6>));
+ map(0x0034, 0x0034).rw(FUNC(avr8_device::gpio_r<GPIOG>), FUNC(avr8_device::port_w<GPIOG>));
+ map(0x0035, 0x0035).w(FUNC(avr8_device::tifr0_w));
+ map(0x0036, 0x0036).w(FUNC(avr8_device::tifr1_w));
+ map(0x0037, 0x0037).w(FUNC(avr8_device::tifr2_w));
+ map(0x003e, 0x003e).w(FUNC(avr8_device::gpior0_w));
+ map(0x003f, 0x003f).w(FUNC(avr8_device::eecr_w));
+ map(0x0043, 0x0043).w(FUNC(avr8_device::gtccr_w));
+ map(0x0044, 0x0044).w(FUNC(avr8_device::tccr0a_w));
+ map(0x0045, 0x0045).w(FUNC(avr8_device::tccr0b_w));
+ map(0x0047, 0x0047).w(FUNC(avr8_device::ocr0a_w));
+ map(0x0048, 0x0048).w(FUNC(avr8_device::ocr0b_w));
+ map(0x004a, 0x004a).w(FUNC(avr8_device::gpior1_w));
+ map(0x004b, 0x004b).w(FUNC(avr8_device::gpior2_w));
+ map(0x004c, 0x004c).w(FUNC(avr8_device::spcr_w));
+ map(0x004d, 0x004d).w(FUNC(avr8_device::spsr_w));
+ map(0x004e, 0x004e).w(FUNC(avr8_device::spdr_w));
+ map(0x0060, 0x0060).w(FUNC(avr8_device::wdtcsr_w));
+ map(0x0061, 0x0061).w(FUNC(avr8_device::clkpr_w));
+ map(0x0064, 0x0064).w(FUNC(avr8_device::prr0_w));
+ map(0x0065, 0x0065).w(FUNC(avr8_device::prr1_w));
+ map(0x0066, 0x0066).w(FUNC(avr8_device::osccal_w));
+ map(0x0068, 0x0068).w(FUNC(avr8_device::pcicr_w));
+ map(0x0069, 0x0069).w(FUNC(avr8_device::eicra_w));
+ map(0x006a, 0x006a).w(FUNC(avr8_device::eicrb_w));
+ map(0x006b, 0x006b).w(FUNC(avr8_device::pcmsk0_w));
+ map(0x006c, 0x006c).w(FUNC(avr8_device::pcmsk1_w));
+ map(0x006d, 0x006d).w(FUNC(avr8_device::pcmsk2_w));
+ map(0x006e, 0x006e).w(FUNC(avr8_device::timsk0_w));
+ map(0x006f, 0x006f).w(FUNC(avr8_device::timsk1_w));
+ map(0x0070, 0x0070).w(FUNC(avr8_device::timsk2_w));
+ map(0x0071, 0x0071).w(FUNC(avr8_device::timsk3_w));
+ map(0x0072, 0x0072).w(FUNC(avr8_device::timsk4_w));
+ map(0x0073, 0x0073).w(FUNC(avr8_device::timsk5_w));
+ map(0x0074, 0x0074).w(FUNC(avr8_device::xmcra_w));
+ map(0x0075, 0x0075).w(FUNC(avr8_device::xmcrb_w));
+ map(0x0078, 0x0078).rw(FUNC(avr8_device::adcl_r), FUNC(avr8_device::adcl_w));
+ map(0x0079, 0x0079).rw(FUNC(avr8_device::adch_r), FUNC(avr8_device::adch_w));
+ map(0x007a, 0x007a).w(FUNC(avr8_device::adcsra_w));
+ map(0x007b, 0x007b).w(FUNC(avr8_device::adcsrb_w));
+ map(0x007c, 0x007c).w(FUNC(avr8_device::admux_w));
+ map(0x007d, 0x007d).w(FUNC(avr8_device::didr2_w));
+ map(0x007e, 0x007e).w(FUNC(avr8_device::didr0_w));
+ map(0x007f, 0x007f).w(FUNC(avr8_device::didr1_w));
+ map(0x0080, 0x0080).w(FUNC(avr8_device::tccr1a_w));
+ map(0x0081, 0x0081).w(FUNC(avr8_device::tccr1b_w));
+ map(0x0082, 0x0082).w(FUNC(avr8_device::tccr1c_w));
+ map(0x0086, 0x0086).w(FUNC(avr8_device::icr1l_w));
+ map(0x0087, 0x0087).w(FUNC(avr8_device::icr1h_w));
+ map(0x0088, 0x0088).w(FUNC(avr8_device::ocr1al_w));
+ map(0x0089, 0x0089).w(FUNC(avr8_device::ocr1ah_w));
+ map(0x008a, 0x008a).w(FUNC(avr8_device::ocr1bl_w));
+ map(0x008b, 0x008b).w(FUNC(avr8_device::ocr1bh_w));
+ map(0x008c, 0x008c).w(FUNC(avr8_device::ocr1cl_w));
+ map(0x008d, 0x008d).w(FUNC(avr8_device::ocr1ch_w));
+ map(0x0090, 0x0090).w(FUNC(avr8_device::tccr3a_w));
+ map(0x0091, 0x0091).w(FUNC(avr8_device::tccr3b_w));
+ map(0x0092, 0x0092).w(FUNC(avr8_device::tccr3c_w));
+ map(0x0096, 0x0096).w(FUNC(avr8_device::icr3l_w));
+ map(0x0097, 0x0097).w(FUNC(avr8_device::icr3h_w));
+ map(0x0098, 0x0098).w(FUNC(avr8_device::ocr3al_w));
+ map(0x0099, 0x0099).w(FUNC(avr8_device::ocr3ah_w));
+ map(0x009a, 0x009a).w(FUNC(avr8_device::ocr3bl_w));
+ map(0x009b, 0x009b).w(FUNC(avr8_device::ocr3bh_w));
+ map(0x009c, 0x009c).w(FUNC(avr8_device::ocr3cl_w));
+ map(0x009d, 0x009d).w(FUNC(avr8_device::ocr3ch_w));
+ map(0x00a0, 0x00a0).w(FUNC(avr8_device::tccr4a_w));
+ map(0x00a1, 0x00a1).w(FUNC(avr8_device::tccr4b_w));
+ map(0x00a2, 0x00a2).w(FUNC(avr8_device::tccr4c_w));
+ map(0x00a4, 0x00a4).w(FUNC(avr8_device::tcnt4l_w));
+ map(0x00a5, 0x00a5).w(FUNC(avr8_device::tcnt4h_w));
+ map(0x00a6, 0x00a6).w(FUNC(avr8_device::icr4l_w));
+ map(0x00a7, 0x00a7).w(FUNC(avr8_device::icr4h_w));
+ map(0x00a8, 0x00a8).w(FUNC(avr8_device::ocr4al_w));
+ map(0x00a9, 0x00a9).w(FUNC(avr8_device::ocr4ah_w));
+ map(0x00aa, 0x00aa).w(FUNC(avr8_device::ocr4bl_w));
+ map(0x00ab, 0x00ab).w(FUNC(avr8_device::ocr4bh_w));
+ map(0x00ac, 0x00ac).w(FUNC(avr8_device::ocr4cl_w));
+ map(0x00ad, 0x00ad).w(FUNC(avr8_device::ocr4ch_w));
+ map(0x00b0, 0x00b0).w(FUNC(avr8_device::tccr2a_w));
+ map(0x00b1, 0x00b1).w(FUNC(avr8_device::tccr2b_w));
+ map(0x00b2, 0x00b2).w(FUNC(avr8_device::tcnt2_w));
+ map(0x00b3, 0x00b3).w(FUNC(avr8_device::ocr2a_w));
+ map(0x00b4, 0x00b4).w(FUNC(avr8_device::ocr2b_w));
+ map(0x00b6, 0x00b6).w(FUNC(avr8_device::assr_w));
+ map(0x00b8, 0x00b8).w(FUNC(avr8_device::twbr_w));
+ map(0x00b9, 0x00b9).rw(FUNC(avr8_device::twsr_r), FUNC(avr8_device::twsr_w));
+ map(0x00ba, 0x00ba).w(FUNC(avr8_device::twar_w));
+ map(0x00bb, 0x00bb).w(FUNC(avr8_device::twdr_w));
+ map(0x00bc, 0x00bc).w(FUNC(avr8_device::twcr_w));
+ map(0x00bd, 0x00bd).w(FUNC(avr8_device::twamr_w));
+ map(0x00c0, 0x00c0).w(FUNC(avr8_device::ucsr0a_w));
+ map(0x00c1, 0x00c1).w(FUNC(avr8_device::ucsr0b_w));
+ map(0x00c2, 0x00c2).w(FUNC(avr8_device::ucsr0c_w));
+}
+
void atmega88_device::atmega88_internal_map(address_map &map)
{
- map(0x0000, 0x00ff).rw(FUNC(atmega88_device::regs_r), FUNC(atmega88_device::regs_w));
+ avr8_device::base_internal_map(map);
}
void atmega168_device::atmega168_internal_map(address_map &map)
{
- map(0x0000, 0x00ff).rw(FUNC(atmega168_device::regs_r), FUNC(atmega168_device::regs_w));
+ avr8_device::base_internal_map(map);
}
void atmega328_device::atmega328_internal_map(address_map &map)
{
- map(0x0000, 0x00ff).rw(FUNC(atmega328_device::regs_r), FUNC(atmega328_device::regs_w));
+ avr8_device::base_internal_map(map);
}
void atmega644_device::atmega644_internal_map(address_map &map)
{
- map(0x0000, 0x00ff).rw(FUNC(atmega644_device::regs_r), FUNC(atmega644_device::regs_w));
+ avr8_device::base_internal_map(map);
}
void atmega1280_device::atmega1280_internal_map(address_map &map)
{
- map(0x0000, 0x01ff).rw(FUNC(atmega1280_device::regs_r), FUNC(atmega1280_device::regs_w));
+ avr8_device::base_internal_map(map);
+ map(0x0100, 0x0100).r(FUNC(atmega1280_device::pin_r<7>));
+ map(0x0102, 0x0102).rw(FUNC(atmega1280_device::gpio_r<GPIOH>), FUNC(atmega1280_device::port_w<GPIOH>));
+ map(0x0103, 0x0103).r(FUNC(atmega1280_device::pin_r<8>));
+ map(0x0105, 0x0105).rw(FUNC(atmega1280_device::gpio_r<GPIOJ>),FUNC(atmega1280_device::port_w<GPIOJ>));
+ map(0x0106, 0x0106).r(FUNC(atmega1280_device::pin_r<9>));
+ map(0x0108, 0x0108).rw(FUNC(atmega1280_device::gpio_r<GPIOK>),FUNC(atmega1280_device::port_w<GPIOK>));
+ map(0x0109, 0x0109).r(FUNC(atmega1280_device::pin_r<10>));
+ map(0x010b, 0x010b).rw(FUNC(atmega1280_device::gpio_r<GPIOL>),FUNC(atmega1280_device::port_w<GPIOL>));
+ map(0x0120, 0x0120).w(FUNC(atmega1280_device::tccr5a_w));
+ map(0x0121, 0x0121).w(FUNC(atmega1280_device::tccr5b_w));
}
void atmega2560_device::atmega2560_internal_map(address_map &map)
{
- map(0x0000, 0x01ff).rw(FUNC(atmega2560_device::regs_r), FUNC(atmega2560_device::regs_w));
+ avr8_device::base_internal_map(map);
+ map(0x0100, 0x0100).r(FUNC(atmega2560_device::pin_r<7>));
+ map(0x0102, 0x0102).rw(FUNC(atmega2560_device::gpio_r<GPIOH>), FUNC(atmega2560_device::port_w<GPIOH>));
+ map(0x0103, 0x0103).r(FUNC(atmega2560_device::pin_r<8>));
+ map(0x0105, 0x0105).rw(FUNC(atmega2560_device::gpio_r<GPIOJ>),FUNC(atmega2560_device::port_w<GPIOJ>));
+ map(0x0106, 0x0106).r(FUNC(atmega2560_device::pin_r<9>));
+ map(0x0108, 0x0108).rw(FUNC(atmega2560_device::gpio_r<GPIOK>),FUNC(atmega2560_device::port_w<GPIOK>));
+ map(0x0109, 0x0109).r(FUNC(atmega2560_device::pin_r<10>));
+ map(0x010b, 0x010b).rw(FUNC(atmega2560_device::gpio_r<GPIOL>),FUNC(atmega2560_device::port_w<GPIOL>));
+ map(0x0120, 0x0120).w(FUNC(atmega2560_device::tccr5a_w));
+ map(0x0121, 0x0121).w(FUNC(atmega2560_device::tccr5b_w));
}
void attiny15_device::attiny15_internal_map(address_map &map)
{
- map(0x00, 0x1f).rw(FUNC(attiny15_device::regs_r), FUNC(attiny15_device::regs_w));
+ avr8_device::base_internal_map(map);
}
//-------------------------------------------------
@@ -644,7 +713,7 @@ void attiny15_device::attiny15_internal_map(address_map &map)
//-------------------------------------------------
atmega88_device::atmega88_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : avr8_device(mconfig, tag, owner, clock, ATMEGA88, 0x0fff, address_map_constructor(FUNC(atmega88_device::atmega88_internal_map), this), 3)
+ : avr8_device<3>(mconfig, tag, owner, clock, ATMEGA88, 0x0fff, address_map_constructor(FUNC(atmega88_device::atmega88_internal_map), this))
{
}
@@ -653,7 +722,7 @@ atmega88_device::atmega88_device(const machine_config &mconfig, const char *tag,
//-------------------------------------------------
atmega168_device::atmega168_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : avr8_device(mconfig, tag, owner, clock, ATMEGA168, 0x1fff, address_map_constructor(FUNC(atmega168_device::atmega168_internal_map), this), 3)
+ : avr8_device<3>(mconfig, tag, owner, clock, ATMEGA168, 0x1fff, address_map_constructor(FUNC(atmega168_device::atmega168_internal_map), this))
{
}
@@ -662,7 +731,7 @@ atmega168_device::atmega168_device(const machine_config &mconfig, const char *ta
//-------------------------------------------------
atmega328_device::atmega328_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : avr8_device(mconfig, tag, owner, clock, ATMEGA328, 0x7fff, address_map_constructor(FUNC(atmega328_device::atmega328_internal_map), this), 3)
+ : avr8_device<3>(mconfig, tag, owner, clock, ATMEGA328, 0x7fff, address_map_constructor(FUNC(atmega328_device::atmega328_internal_map), this))
{
}
@@ -671,7 +740,7 @@ atmega328_device::atmega328_device(const machine_config &mconfig, const char *ta
//-------------------------------------------------
atmega644_device::atmega644_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : avr8_device(mconfig, tag, owner, clock, ATMEGA644, 0xffff, address_map_constructor(FUNC(atmega644_device::atmega644_internal_map), this), 3)
+ : avr8_device<3>(mconfig, tag, owner, clock, ATMEGA644, 0xffff, address_map_constructor(FUNC(atmega644_device::atmega644_internal_map), this))
{
}
@@ -680,7 +749,7 @@ atmega644_device::atmega644_device(const machine_config &mconfig, const char *ta
//-------------------------------------------------
atmega1280_device::atmega1280_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : avr8_device(mconfig, tag, owner, clock, ATMEGA1280, 0x1ffff, address_map_constructor(FUNC(atmega1280_device::atmega1280_internal_map), this), 6)
+ : avr8_device<6>(mconfig, tag, owner, clock, ATMEGA1280, 0x1ffff, address_map_constructor(FUNC(atmega1280_device::atmega1280_internal_map), this))
{
}
@@ -689,7 +758,7 @@ atmega1280_device::atmega1280_device(const machine_config &mconfig, const char *
//-------------------------------------------------
atmega2560_device::atmega2560_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : avr8_device(mconfig, tag, owner, clock, ATMEGA2560, 0x1ffff, address_map_constructor(FUNC(atmega2560_device::atmega2560_internal_map), this), 6)
+ : avr8_device<6>(mconfig, tag, owner, clock, ATMEGA2560, 0x1ffff, address_map_constructor(FUNC(atmega2560_device::atmega2560_internal_map), this))
{
}
@@ -698,68 +767,196 @@ atmega2560_device::atmega2560_device(const machine_config &mconfig, const char *
//-------------------------------------------------
attiny15_device::attiny15_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : avr8_device(mconfig, tag, owner, clock, ATTINY15, 0x03ff, address_map_constructor(FUNC(attiny15_device::attiny15_internal_map), this), 2)
+ : avr8_device<2>(mconfig, tag, owner, clock, ATTINY15, 0x03ff, address_map_constructor(FUNC(attiny15_device::attiny15_internal_map), this))
{
}
//-------------------------------------------------
-// avr8_device - constructor
+// avr8_base_device - constructor
//-------------------------------------------------
-avr8_device::avr8_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, const device_type type, uint32_t addr_mask, address_map_constructor internal_map, int32_t num_timers)
+avr8_base_device::avr8_base_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, const device_type type, uint32_t addr_mask, address_map_constructor internal_map)
: cpu_device(mconfig, type, tag, owner, clock)
- , m_shifted_pc(0)
, m_program_config("program", ENDIANNESS_LITTLE, 8, 22)
, m_data_config("data", ENDIANNESS_LITTLE, 8, 16, 0, internal_map)
- , m_io_config("io", ENDIANNESS_LITTLE, 8, 4)
, m_eeprom(*this, finder_base::DUMMY_TAG)
, m_lfuses(0x62)
, m_hfuses(0x99)
, m_efuses(0xff)
, m_lock_bits(0xff)
+ , m_r(*this, "regs")
, m_pc(0)
- , m_num_timers(num_timers)
+ , m_addr_mask((addr_mask << 1) | 1)
+ , m_interrupt_pending(false)
+{
+}
+
+template <int NumTimers>
+avr8_device<NumTimers>::avr8_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, const device_type type, uint32_t addr_mask, address_map_constructor internal_map)
+ : avr8_base_device(mconfig, tag, owner, clock, type, addr_mask, internal_map)
+ , m_gpio_out_cb(*this)
+ , m_gpio_in_cb(*this, 0)
+ , m_adc_in_cb(*this, 0)
+ , m_adc_timer(nullptr)
, m_spi_active(false)
, m_spi_prescale(0)
, m_spi_prescale_count(0)
- , m_addr_mask(addr_mask)
- , m_interrupt_pending(false)
{
-}
+ // Fill in default callbacks
+ for (int i = 0; i < 8*4; i++)
+ {
+ m_timer0_ticks[i] = timer_func(&avr8_device<NumTimers>::timer0_tick_default, this);
+ }
+ for (int i = 0; i < 8; i++)
+ {
+ m_timer2_ticks[i] = timer_func(&avr8_device<NumTimers>::timer2_tick_default, this);
+ }
+
+ // Fill in the mode-specific callbacks
+ for (int i = 0; i < 8; i++)
+ {
+ for (int j = 1; j < 4; j++)
+ {
+ switch (i)
+ {
+ case 0:
+ m_timer0_ticks[(i << 2) + j] = timer_func(&avr8_device<NumTimers>::timer0_tick_norm, this);
+ break;
+ case 1:
+ m_timer0_ticks[(i << 2) + j] = timer_func(&avr8_device<NumTimers>::timer0_tick_pwm_pc, this);
+ break;
+ case 3:
+ m_timer0_ticks[(i << 2) + j] = timer_func(&avr8_device<NumTimers>::timer0_tick_fast_pwm, this);
+ break;
+ case 5:
+ m_timer0_ticks[(i << 2) + j] = timer_func(&avr8_device<NumTimers>::timer0_tick_pwm_pc_cmp, this);
+ break;
+ case 7:
+ m_timer0_ticks[(i << 2) + j] = timer_func(&avr8_device<NumTimers>::timer0_tick_fast_pwm_cmp, this);
+ break;
+ }
+ }
+ }
+ m_timer0_ticks[(WGM02_CTC_CMP << 2) | 0] = timer_func(&avr8_device<NumTimers>::timer0_tick_ctc_norm, this);
+ m_timer0_ticks[(WGM02_CTC_CMP << 2) | 1] = timer_func(&avr8_device<NumTimers>::timer0_tick_ctc_toggle, this);
+ m_timer0_ticks[(WGM02_CTC_CMP << 2) | 2] = timer_func(&avr8_device<NumTimers>::timer0_tick_ctc_clear, this);
+ m_timer0_ticks[(WGM02_CTC_CMP << 2) | 3] = timer_func(&avr8_device<NumTimers>::timer0_tick_ctc_set, this);
+
+ for (int i = 0; i < 16; i++)
+ {
+ m_timer1_ticks[(WGM1_NORMAL << 4) | i] = timer_func(&avr8_device<NumTimers>::timer1_tick_normal, this);
+ m_timer1_ticks[(WGM1_PWM_8_PC << 4) | i] = timer_func(&avr8_device<NumTimers>::timer1_tick_pwm8_pc, this);
+ m_timer1_ticks[(WGM1_PWM_9_PC << 4) | i] = timer_func(&avr8_device<NumTimers>::timer1_tick_pwm9_pc, this);
+ m_timer1_ticks[(WGM1_PWM_10_PC << 4) | i] = timer_func(&avr8_device<NumTimers>::timer1_tick_pwm10_pc, this);
+ m_timer1_ticks[(WGM1_FAST_PWM_8 << 4) | i] = timer_func(&avr8_device<NumTimers>::timer1_tick_fast_pwm8, this);
+ m_timer1_ticks[(WGM1_FAST_PWM_9 << 4) | i] = timer_func(&avr8_device<NumTimers>::timer1_tick_fast_pwm9, this);
+ m_timer1_ticks[(WGM1_FAST_PWM_10 << 4) | i] = timer_func(&avr8_device<NumTimers>::timer1_tick_fast_pwm10, this);
+ m_timer1_ticks[(WGM1_PWM_PFC_ICR << 4) | i] = timer_func(&avr8_device<NumTimers>::timer1_tick_pwm_pfc_icr, this);
+ m_timer1_ticks[(WGM1_PWM_PFC_OCR << 4) | i] = timer_func(&avr8_device<NumTimers>::timer1_tick_pwm_pfc_ocr, this);
+ m_timer1_ticks[(WGM1_PWM_PC_ICR << 4) | i] = timer_func(&avr8_device<NumTimers>::timer1_tick_pwm_pc_icr, this);
+ m_timer1_ticks[(WGM1_PWM_PC_OCR << 4) | i] = timer_func(&avr8_device<NumTimers>::timer1_tick_pwm_pc_ocr, this);
+ m_timer1_ticks[(WGM1_CTC_ICR << 4) | i] = timer_func(&avr8_device<NumTimers>::timer1_tick_ctc_icr, this);
+ m_timer1_ticks[(WGM1_RESERVED << 4) | i] = timer_func(&avr8_device<NumTimers>::timer1_tick_resv, this);
+ }
+
+ m_timer1_ticks[(WGM1_CTC_OCR << 4) | 0] = timer_func(&avr8_device<NumTimers>::timer1_tick_ctc_ocr_norm_norm, this);
+ m_timer1_ticks[(WGM1_CTC_OCR << 4) | 1] = timer_func(&avr8_device<NumTimers>::timer1_tick_ctc_ocr_norm_toggle, this);
+ m_timer1_ticks[(WGM1_CTC_OCR << 4) | 2] = timer_func(&avr8_device<NumTimers>::timer1_tick_ctc_ocr_norm_clear, this);
+ m_timer1_ticks[(WGM1_CTC_OCR << 4) | 3] = timer_func(&avr8_device<NumTimers>::timer1_tick_ctc_ocr_norm_set, this);
+ m_timer1_ticks[(WGM1_CTC_OCR << 4) | 4] = timer_func(&avr8_device<NumTimers>::timer1_tick_ctc_ocr_toggle_norm, this);
+ m_timer1_ticks[(WGM1_CTC_OCR << 4) | 5] = timer_func(&avr8_device<NumTimers>::timer1_tick_ctc_ocr_toggle_toggle, this);
+ m_timer1_ticks[(WGM1_CTC_OCR << 4) | 6] = timer_func(&avr8_device<NumTimers>::timer1_tick_ctc_ocr_toggle_clear, this);
+ m_timer1_ticks[(WGM1_CTC_OCR << 4) | 7] = timer_func(&avr8_device<NumTimers>::timer1_tick_ctc_ocr_toggle_set, this);
+ m_timer1_ticks[(WGM1_CTC_OCR << 4) | 8] = timer_func(&avr8_device<NumTimers>::timer1_tick_ctc_ocr_clear_norm, this);
+ m_timer1_ticks[(WGM1_CTC_OCR << 4) | 9] = timer_func(&avr8_device<NumTimers>::timer1_tick_ctc_ocr_clear_toggle, this);
+ m_timer1_ticks[(WGM1_CTC_OCR << 4) | 10] = timer_func(&avr8_device<NumTimers>::timer1_tick_ctc_ocr_clear_clear, this);
+ m_timer1_ticks[(WGM1_CTC_OCR << 4) | 11] = timer_func(&avr8_device<NumTimers>::timer1_tick_ctc_ocr_clear_set, this);
+ m_timer1_ticks[(WGM1_CTC_OCR << 4) | 12] = timer_func(&avr8_device<NumTimers>::timer1_tick_ctc_ocr_set_norm, this);
+ m_timer1_ticks[(WGM1_CTC_OCR << 4) | 13] = timer_func(&avr8_device<NumTimers>::timer1_tick_ctc_ocr_set_toggle, this);
+ m_timer1_ticks[(WGM1_CTC_OCR << 4) | 14] = timer_func(&avr8_device<NumTimers>::timer1_tick_ctc_ocr_set_clear, this);
+ m_timer1_ticks[(WGM1_CTC_OCR << 4) | 15] = timer_func(&avr8_device<NumTimers>::timer1_tick_ctc_ocr_set_set, this);
+
+ m_timer1_ticks[(WGM1_FAST_PWM_ICR << 4) | 0] = timer_func(&avr8_device<NumTimers>::timer1_tick_fast_pwm_icr_norm_norm, this);
+ m_timer1_ticks[(WGM1_FAST_PWM_ICR << 4) | 1] = timer_func(&avr8_device<NumTimers>::timer1_tick_fast_pwm_icr_norm_toggle, this);
+ m_timer1_ticks[(WGM1_FAST_PWM_ICR << 4) | 2] = timer_func(&avr8_device<NumTimers>::timer1_tick_fast_pwm_icr_norm_clear, this);
+ m_timer1_ticks[(WGM1_FAST_PWM_ICR << 4) | 3] = timer_func(&avr8_device<NumTimers>::timer1_tick_fast_pwm_icr_norm_set, this);
+ m_timer1_ticks[(WGM1_FAST_PWM_ICR << 4) | 4] = timer_func(&avr8_device<NumTimers>::timer1_tick_fast_pwm_icr_toggle_norm, this);
+ m_timer1_ticks[(WGM1_FAST_PWM_ICR << 4) | 5] = timer_func(&avr8_device<NumTimers>::timer1_tick_fast_pwm_icr_toggle_toggle, this);
+ m_timer1_ticks[(WGM1_FAST_PWM_ICR << 4) | 6] = timer_func(&avr8_device<NumTimers>::timer1_tick_fast_pwm_icr_toggle_clear, this);
+ m_timer1_ticks[(WGM1_FAST_PWM_ICR << 4) | 7] = timer_func(&avr8_device<NumTimers>::timer1_tick_fast_pwm_icr_toggle_set, this);
+ m_timer1_ticks[(WGM1_FAST_PWM_ICR << 4) | 8] = timer_func(&avr8_device<NumTimers>::timer1_tick_fast_pwm_icr_clear_norm, this);
+ m_timer1_ticks[(WGM1_FAST_PWM_ICR << 4) | 9] = timer_func(&avr8_device<NumTimers>::timer1_tick_fast_pwm_icr_clear_toggle, this);
+ m_timer1_ticks[(WGM1_FAST_PWM_ICR << 4) | 10] = timer_func(&avr8_device<NumTimers>::timer1_tick_fast_pwm_icr_clear_clear, this);
+ m_timer1_ticks[(WGM1_FAST_PWM_ICR << 4) | 11] = timer_func(&avr8_device<NumTimers>::timer1_tick_fast_pwm_icr_clear_set, this);
+ m_timer1_ticks[(WGM1_FAST_PWM_ICR << 4) | 12] = timer_func(&avr8_device<NumTimers>::timer1_tick_fast_pwm_icr_set_norm, this);
+ m_timer1_ticks[(WGM1_FAST_PWM_ICR << 4) | 13] = timer_func(&avr8_device<NumTimers>::timer1_tick_fast_pwm_icr_set_toggle, this);
+ m_timer1_ticks[(WGM1_FAST_PWM_ICR << 4) | 14] = timer_func(&avr8_device<NumTimers>::timer1_tick_fast_pwm_icr_set_clear, this);
+ m_timer1_ticks[(WGM1_FAST_PWM_ICR << 4) | 15] = timer_func(&avr8_device<NumTimers>::timer1_tick_fast_pwm_icr_set_set, this);
+
+ m_timer1_ticks[(WGM1_FAST_PWM_OCR << 4) | 0] = timer_func(&avr8_device<NumTimers>::timer1_tick_fast_pwm_ocr_norm_norm, this);
+ m_timer1_ticks[(WGM1_FAST_PWM_OCR << 4) | 1] = timer_func(&avr8_device<NumTimers>::timer1_tick_fast_pwm_ocr_norm_toggle, this);
+ m_timer1_ticks[(WGM1_FAST_PWM_OCR << 4) | 2] = timer_func(&avr8_device<NumTimers>::timer1_tick_fast_pwm_ocr_norm_clear, this);
+ m_timer1_ticks[(WGM1_FAST_PWM_OCR << 4) | 3] = timer_func(&avr8_device<NumTimers>::timer1_tick_fast_pwm_ocr_norm_set, this);
+ m_timer1_ticks[(WGM1_FAST_PWM_OCR << 4) | 4] = timer_func(&avr8_device<NumTimers>::timer1_tick_fast_pwm_ocr_toggle_norm, this);
+ m_timer1_ticks[(WGM1_FAST_PWM_OCR << 4) | 5] = timer_func(&avr8_device<NumTimers>::timer1_tick_fast_pwm_ocr_toggle_toggle, this);
+ m_timer1_ticks[(WGM1_FAST_PWM_OCR << 4) | 6] = timer_func(&avr8_device<NumTimers>::timer1_tick_fast_pwm_ocr_toggle_clear, this);
+ m_timer1_ticks[(WGM1_FAST_PWM_OCR << 4) | 7] = timer_func(&avr8_device<NumTimers>::timer1_tick_fast_pwm_ocr_toggle_set, this);
+ m_timer1_ticks[(WGM1_FAST_PWM_OCR << 4) | 8] = timer_func(&avr8_device<NumTimers>::timer1_tick_fast_pwm_ocr_clear_norm, this);
+ m_timer1_ticks[(WGM1_FAST_PWM_OCR << 4) | 9] = timer_func(&avr8_device<NumTimers>::timer1_tick_fast_pwm_ocr_clear_toggle, this);
+ m_timer1_ticks[(WGM1_FAST_PWM_OCR << 4) | 10] = timer_func(&avr8_device<NumTimers>::timer1_tick_fast_pwm_ocr_clear_clear, this);
+ m_timer1_ticks[(WGM1_FAST_PWM_OCR << 4) | 11] = timer_func(&avr8_device<NumTimers>::timer1_tick_fast_pwm_ocr_clear_set, this);
+ m_timer1_ticks[(WGM1_FAST_PWM_OCR << 4) | 12] = timer_func(&avr8_device<NumTimers>::timer1_tick_fast_pwm_ocr_set_norm, this);
+ m_timer1_ticks[(WGM1_FAST_PWM_OCR << 4) | 13] = timer_func(&avr8_device<NumTimers>::timer1_tick_fast_pwm_ocr_set_toggle, this);
+ m_timer1_ticks[(WGM1_FAST_PWM_OCR << 4) | 14] = timer_func(&avr8_device<NumTimers>::timer1_tick_fast_pwm_ocr_set_clear, this);
+ m_timer1_ticks[(WGM1_FAST_PWM_OCR << 4) | 15] = timer_func(&avr8_device<NumTimers>::timer1_tick_fast_pwm_ocr_set_set, this);
+
+ m_timer2_ticks[WGM02_NORMAL] = timer_func(&avr8_device<NumTimers>::timer2_tick_norm, this);
+ m_timer2_ticks[WGM02_PWM_PC] = timer_func(&avr8_device<NumTimers>::timer2_tick_default, this);
+ m_timer2_ticks[WGM02_CTC_CMP] = timer_func(&avr8_device<NumTimers>::timer2_tick_default, this);
+ m_timer2_ticks[WGM02_FAST_PWM] = timer_func(&avr8_device<NumTimers>::timer2_tick_fast_pwm, this);
+ m_timer2_ticks[WGM02_RESERVED0] = timer_func(&avr8_device<NumTimers>::timer2_tick_default, this);
+ m_timer2_ticks[WGM02_PWM_PC_CMP] = timer_func(&avr8_device<NumTimers>::timer2_tick_default, this);
+ m_timer2_ticks[WGM02_RESERVED1] = timer_func(&avr8_device<NumTimers>::timer2_tick_default, this);
+ m_timer2_ticks[WGM02_FAST_PWM_CMP] = timer_func(&avr8_device<NumTimers>::timer2_tick_fast_pwm_cmp, this);
+
+ m_timer0_tick = m_timer0_ticks[0];
+ m_timer1_tick = m_timer1_ticks[0];
+ m_timer2_tick = m_timer2_ticks[0];
+}
//-------------------------------------------------
-// static_set_low_fuses
+// set_low_fuses
//-------------------------------------------------
-void avr8_device::set_low_fuses(const uint8_t byte)
+void avr8_base_device::set_low_fuses(const uint8_t byte)
{
m_lfuses = byte;
}
//-------------------------------------------------
-// static_set_high_fuses
+// set_high_fuses
//-------------------------------------------------
-void avr8_device::set_high_fuses(const uint8_t byte)
+void avr8_base_device::set_high_fuses(const uint8_t byte)
{
m_hfuses = byte;
}
//-------------------------------------------------
-// static_set_extended_fuses
+// set_extended_fuses
//-------------------------------------------------
-void avr8_device::set_extended_fuses(const uint8_t byte)
+void avr8_base_device::set_extended_fuses(const uint8_t byte)
{
m_efuses = byte;
}
//-------------------------------------------------
-// static_set_lock_bits
+// set_lock_bits
//-------------------------------------------------
-void avr8_device::set_lock_bits(const uint8_t byte)
+void avr8_base_device::set_lock_bits(const uint8_t byte)
{
m_lock_bits = byte;
}
@@ -769,10 +966,10 @@ void avr8_device::set_lock_bits(const uint8_t byte)
// instruction
//-------------------------------------------------
-void avr8_device::unimplemented_opcode(uint32_t op)
+void avr8_base_device::unimplemented_opcode(uint32_t op)
{
// machine().debug_break();
- fatalerror("AVR8: unknown opcode (%08x) at %08x\n", op, m_shifted_pc);
+ fatalerror("AVR8: unknown opcode (%08x) at %08x\n", op, m_pc);
}
@@ -781,7 +978,7 @@ void avr8_device::unimplemented_opcode(uint32_t op)
// bytes long
//-------------------------------------------------
-inline bool avr8_device::is_long_opcode(uint16_t op)
+inline bool avr8_base_device::is_long_opcode(uint16_t op)
{
if ((op & 0xf000) == 0x9000)
{
@@ -807,22 +1004,21 @@ inline bool avr8_device::is_long_opcode(uint16_t op)
// device_start - start up the device
//-------------------------------------------------
-void avr8_device::device_start()
+void avr8_base_device::device_start()
{
m_pc = 0;
m_program = &space(AS_PROGRAM);
m_data = &space(AS_DATA);
- m_io = &space(AS_IO);
// register our state for the debugger
- state_add(STATE_GENPC, "GENPC", m_shifted_pc).noshow();
- state_add(STATE_GENPCBASE, "CURPC", m_shifted_pc).noshow();
- state_add(STATE_GENFLAGS, "GENFLAGS", m_r[AVR8_REGIDX_SREG]).callimport().callexport().formatstr("%8s").noshow();
- state_add(AVR8_SREG, "STATUS", m_r[AVR8_REGIDX_SREG]).mask(0xff);
- state_add(AVR8_PC, "PC", m_shifted_pc).mask(m_addr_mask);
- state_add(AVR8_SPH, "SPH", m_r[AVR8_REGIDX_SPH]).mask(0xff);
- state_add(AVR8_SPL, "SPL", m_r[AVR8_REGIDX_SPL]).mask(0xff);
+ state_add(STATE_GENPC, "GENPC", m_pc).callexport().noshow();
+ state_add(STATE_GENPCBASE, "CURPC", m_pc).callexport().noshow();
+ state_add(STATE_GENFLAGS, "GENFLAGS", m_r[SREG]).callimport().callexport().formatstr("%8s").noshow();
+ state_add(AVR8_SREG, "STATUS", m_r[SREG]).mask(0xff);
+ state_add(AVR8_PC, "PC", m_pc).mask(m_addr_mask).callexport();
+ state_add(AVR8_SPH, "SPH", m_r[SPH]).mask(0xff);
+ state_add(AVR8_SPL, "SPL", m_r[SPL]).mask(0xff);
state_add(AVR8_R0, "R0", m_r[ 0]).mask(0xff);
state_add(AVR8_R1, "R1", m_r[ 1]).mask(0xff);
state_add(AVR8_R2, "R2", m_r[ 2]).mask(0xff);
@@ -863,24 +1059,6 @@ void avr8_device::device_start()
save_item(NAME(m_efuses));
save_item(NAME(m_lock_bits));
save_item(NAME(m_pc));
- save_item(NAME(m_r));
-
- // Timers
- save_item(NAME(m_timer_top));
- save_item(NAME(m_timer_increment));
- save_item(NAME(m_timer_prescale));
- save_item(NAME(m_timer_prescale_count));
- save_item(NAME(m_ocr2_not_reached_yet));
- save_item(NAME(m_wgm1));
- save_item(NAME(m_timer1_compare_mode));
- save_item(NAME(m_ocr1));
- save_item(NAME(m_timer1_count));
-
- // SPI
- save_item(NAME(m_spi_active));
- save_item(NAME(m_spi_prescale));
- save_item(NAME(m_spi_prescale_count));
- save_item(NAME(m_spi_prescale_countdown));
// Misc.
save_item(NAME(m_addr_mask));
@@ -906,11 +1084,39 @@ void avr8_device::device_start()
populate_shift_flag_cache();
}
+template <int NumTimers>
+void avr8_device<NumTimers>::device_start()
+{
+ avr8_base_device::device_start();
+
+ m_adc_timer = timer_alloc(FUNC(avr8_device<NumTimers>::adc_conversion_complete), this);
+
+ // Timers
+ save_item(NAME(m_timer_top));
+ save_item(NAME(m_timer_prescale));
+ save_item(NAME(m_timer_prescale_count));
+ save_item(NAME(m_ocr2_not_reached_yet));
+ save_item(NAME(m_ocr1));
+
+ // ADC
+ save_item(NAME(m_adc_sample));
+ save_item(NAME(m_adc_result));
+ save_item(NAME(m_adc_data));
+ save_item(NAME(m_adc_first));
+ save_item(NAME(m_adc_hold));
+
+ // SPI
+ save_item(NAME(m_spi_active));
+ save_item(NAME(m_spi_prescale));
+ save_item(NAME(m_spi_prescale_count));
+ save_item(NAME(m_spi_prescale_countdown));
+}
+
//-------------------------------------------------
// device_reset - reset the device
//-------------------------------------------------
-void avr8_device::device_reset()
+void avr8_base_device::device_reset()
{
logerror("AVR low fuse bits: 0x%02X\n", m_lfuses);
logerror("AVR high fuse bits: 0x%02X\n", m_hfuses);
@@ -920,23 +1126,23 @@ void avr8_device::device_reset()
switch ((m_hfuses & (BOOTSZ1 | BOOTSZ0)) >> 1)
{
case 0:
- if (m_addr_mask <= 0x0fff) { m_boot_size = 1024; }
- else if (m_addr_mask <= 0x7fff) { m_boot_size = 2048; }
+ if (m_addr_mask <= 0x1fff) { m_boot_size = 1024; }
+ else if (m_addr_mask <= 0xffff) { m_boot_size = 2048; }
else { m_boot_size = 4096; }
break;
case 1:
- if (m_addr_mask <= 0x0fff) { m_boot_size = 512; }
- else if (m_addr_mask <= 0x7fff) { m_boot_size = 1024; }
+ if (m_addr_mask <= 0x1fff) { m_boot_size = 512; }
+ else if (m_addr_mask <= 0xffff) { m_boot_size = 1024; }
else { m_boot_size = 2048; }
break;
case 2:
- if (m_addr_mask <= 0x0fff) { m_boot_size = 256; }
- else if (m_addr_mask <= 0x7fff) { m_boot_size = 512; }
+ if (m_addr_mask <= 0x1fff) { m_boot_size = 256; }
+ else if (m_addr_mask <= 0xffff) { m_boot_size = 512; }
else { m_boot_size = 1024; }
break;
case 3:
- if (m_addr_mask <= 0x0fff) { m_boot_size = 128; }
- else if (m_addr_mask <= 0x7fff) { m_boot_size = 256; }
+ if (m_addr_mask <= 0x1fff) { m_boot_size = 128; }
+ else if (m_addr_mask <= 0xffff) { m_boot_size = 256; }
else { m_boot_size = 512; }
break;
default:
@@ -945,11 +1151,10 @@ void avr8_device::device_reset()
if (m_hfuses & BOOTRST)
{
- m_shifted_pc = 0x0000;
+ m_pc = 0x0000;
LOGMASKED(LOG_BOOT, "Booting AVR core from address 0x0000\n");
} else {
- m_shifted_pc = (m_addr_mask + 1) - 2*m_boot_size;
- m_pc = m_shifted_pc >> 1;
+ m_pc = (m_addr_mask + 1) - 2 * m_boot_size;
LOGMASKED(LOG_BOOT, "AVR Boot loader section size: %d words\n", m_boot_size);
}
@@ -958,29 +1163,35 @@ void avr8_device::device_reset()
m_r[i] = 0;
}
+ m_interrupt_pending = false;
+}
+
+template <int NumTimers>
+void avr8_device<NumTimers>::device_reset()
+{
+ m_adc_sample = 0;
+ m_adc_result = 0;
+ m_adc_data = 0;
+ m_adc_first = true;
+ m_adc_hold = false;
+
m_spi_active = false;
m_spi_prescale = 0;
m_spi_prescale_count = 0;
- for (int t = 0; t < m_num_timers; t++)
+ for (int t = 0; t < NumTimers; t++)
{
m_timer_top[t] = 0;
- m_timer_increment[t] = 1;
- m_timer_prescale[t] = 0;
+ m_timer_prescale[t] = 0xffff;
m_timer_prescale_count[t] = 0;
}
- m_wgm1 = 0;
- m_timer1_compare_mode[0] = 0;
- m_timer1_compare_mode[1] = 0;
for (int reg = AVR8_REG_A; reg <= AVR8_REG_C; reg++)
{
m_ocr1[reg] = 0;
}
- m_timer1_count = 0;
m_ocr2_not_reached_yet = true;
- m_interrupt_pending = false;
}
//-------------------------------------------------
@@ -988,12 +1199,11 @@ void avr8_device::device_reset()
// of the CPU's address spaces
//-------------------------------------------------
-device_memory_interface::space_config_vector avr8_device::memory_space_config() const
+device_memory_interface::space_config_vector avr8_base_device::memory_space_config() const
{
return space_config_vector {
std::make_pair(AS_PROGRAM, &m_program_config),
- std::make_pair(AS_DATA, &m_data_config),
- std::make_pair(AS_IO, &m_io_config)
+ std::make_pair(AS_DATA, &m_data_config)
};
}
@@ -1003,26 +1213,30 @@ device_memory_interface::space_config_vector avr8_device::memory_space_config()
// for the debugger
//-------------------------------------------------
-void avr8_device::state_string_export(const device_state_entry &entry, std::string &str) const
+void avr8_base_device::state_string_export(const device_state_entry &entry, std::string &str) const
{
switch (entry.index())
{
+ case STATE_GENPC:
+ case STATE_GENPCBASE:
+ case AVR8_PC:
+ str = string_format("%05x", m_pc << 1);
+ break;
case STATE_GENFLAGS:
str = string_format("%c%c%c%c%c%c%c%c",
- (m_r[AVR8_REGIDX_SREG] & 0x80) ? 'I' : '-',
- (m_r[AVR8_REGIDX_SREG] & 0x40) ? 'T' : '-',
- (m_r[AVR8_REGIDX_SREG] & 0x20) ? 'H' : '-',
- (m_r[AVR8_REGIDX_SREG] & 0x10) ? 'S' : '-',
- (m_r[AVR8_REGIDX_SREG] & 0x08) ? 'V' : '-',
- (m_r[AVR8_REGIDX_SREG] & 0x04) ? 'N' : '-',
- (m_r[AVR8_REGIDX_SREG] & 0x02) ? 'Z' : '-',
- (m_r[AVR8_REGIDX_SREG] & 0x01) ? 'C' : '-');
+ (m_r[SREG] & 0x80) ? 'I' : '-',
+ (m_r[SREG] & 0x40) ? 'T' : '-',
+ (m_r[SREG] & 0x20) ? 'H' : '-',
+ (m_r[SREG] & 0x10) ? 'S' : '-',
+ (m_r[SREG] & 0x08) ? 'V' : '-',
+ (m_r[SREG] & 0x04) ? 'N' : '-',
+ (m_r[SREG] & 0x02) ? 'Z' : '-',
+ (m_r[SREG] & 0x01) ? 'C' : '-');
break;
}
}
-
-std::unique_ptr<util::disasm_interface> avr8_device::create_disassembler()
+std::unique_ptr<util::disasm_interface> avr8_base_device::create_disassembler()
{
return std::make_unique<avr8_disassembler>();
}
@@ -1032,21 +1246,21 @@ std::unique_ptr<util::disasm_interface> avr8_device::create_disassembler()
// MEMORY ACCESSORS
//**************************************************************************
-inline void avr8_device::push(uint8_t val)
+inline void avr8_base_device::push(uint8_t val)
{
uint16_t sp = SPREG;
m_data->write_byte(sp, val);
sp--;
- m_r[AVR8_REGIDX_SPL] = sp & 0x00ff;
- m_r[AVR8_REGIDX_SPH] = (sp >> 8) & 0x00ff;
+ m_r[SPL] = sp & 0x00ff;
+ m_r[SPH] = (sp >> 8) & 0x00ff;
}
-inline uint8_t avr8_device::pop()
+inline uint8_t avr8_base_device::pop()
{
uint16_t sp = SPREG;
sp++;
- m_r[AVR8_REGIDX_SPL] = sp & 0x00ff;
- m_r[AVR8_REGIDX_SPH] = (sp >> 8) & 0x00ff;
+ m_r[SPL] = sp & 0x00ff;
+ m_r[SPH] = (sp >> 8) & 0x00ff;
return m_data->read_byte(sp);
}
@@ -1054,17 +1268,16 @@ inline uint8_t avr8_device::pop()
// IRQ HANDLING
//**************************************************************************
-void avr8_device::set_irq_line(uint16_t vector, int state)
+void avr8_base_device::set_irq_line(uint16_t vector, int state)
{
if (state)
{
- if (SREG_R(AVR8_SREG_I))
+ if (BIT(m_r[SREG], SREG_I))
{
- SREG_W(AVR8_SREG_I, 0);
- push(m_pc & 0x00ff);
- push((m_pc >> 8) & 0x00ff);
- m_pc = vector;
- m_shifted_pc = vector << 1;
+ m_r[SREG] &= ~SREG_MASK_I;
+ push((m_pc >> 1) & 0x00ff);
+ push((m_pc >> 9) & 0x00ff);
+ m_pc = vector << 1;
}
else
{
@@ -1073,31 +1286,22 @@ void avr8_device::set_irq_line(uint16_t vector, int state)
}
}
-struct interrupt_condition
+const avr8_base_device::interrupt_condition avr8_base_device::s_int_conditions[avr8_base_device::INTIDX_COUNT] =
{
- uint8_t m_intindex;
- uint8_t m_intreg;
- uint8_t m_intmask;
- uint8_t m_regindex;
- uint8_t m_regmask;
+ { AVR8_INT_SPI_STC, SPCR, SPCR_SPIE_MASK, SPSR, SPSR_SPIF_MASK },
+ { AVR8_INT_T0COMPB, TIMSK0, TIMSK0_OCIE0B_MASK, TIFR0, TIFR0_OCF0B_MASK },
+ { AVR8_INT_T0COMPA, TIMSK0, TIMSK0_OCIE0A_MASK, TIFR0, TIFR0_OCF0A_MASK },
+ { AVR8_INT_T0OVF, TIMSK0, TIMSK0_TOIE0_MASK, TIFR0, TIFR0_TOV0_MASK },
+ { AVR8_INT_T1CAPT, TIMSK1, TIMSK1_ICIE1_MASK, TIFR1, TIFR1_ICF1_MASK },
+ { AVR8_INT_T1COMPB, TIMSK1, TIMSK1_OCIE1B_MASK, TIFR1, TIFR1_OCF1B_MASK },
+ { AVR8_INT_T1COMPA, TIMSK1, TIMSK1_OCIE1A_MASK, TIFR1, TIFR1_OCF1A_MASK },
+ { AVR8_INT_T1OVF, TIMSK1, TIMSK1_TOIE1_MASK, TIFR1, TIFR1_TOV1_MASK },
+ { AVR8_INT_T2COMPB, TIMSK2, TIMSK2_OCIE2B_MASK, TIFR2, TIFR2_OCF2B_MASK },
+ { AVR8_INT_T2COMPA, TIMSK2, TIMSK2_OCIE2A_MASK, TIFR2, TIFR2_OCF2A_MASK },
+ { AVR8_INT_T2OVF, TIMSK2, TIMSK2_TOIE2_MASK, TIFR2, TIFR2_TOV2_MASK }
};
-static const interrupt_condition s_int_conditions[AVR8_INTIDX_COUNT] =
-{
- { AVR8_INT_SPI_STC, AVR8_REGIDX_SPCR, AVR8_SPCR_SPIE_MASK, AVR8_REGIDX_SPSR, AVR8_SPSR_SPIF_MASK },
- { AVR8_INT_T0COMPB, AVR8_REGIDX_TIMSK0, AVR8_TIMSK0_OCIE0B_MASK, AVR8_REGIDX_TIFR0, AVR8_TIFR0_OCF0B_MASK },
- { AVR8_INT_T0COMPA, AVR8_REGIDX_TIMSK0, AVR8_TIMSK0_OCIE0A_MASK, AVR8_REGIDX_TIFR0, AVR8_TIFR0_OCF0A_MASK },
- { AVR8_INT_T0OVF, AVR8_REGIDX_TIMSK0, AVR8_TIMSK0_TOIE0_MASK, AVR8_REGIDX_TIFR0, AVR8_TIFR0_TOV0_MASK },
- { AVR8_INT_T1CAPT, AVR8_REGIDX_TIMSK1, AVR8_TIMSK1_ICIE1_MASK, AVR8_REGIDX_TIFR1, AVR8_TIFR1_ICF1_MASK },
- { AVR8_INT_T1COMPB, AVR8_REGIDX_TIMSK1, AVR8_TIMSK1_OCIE1B_MASK, AVR8_REGIDX_TIFR1, AVR8_TIFR1_OCF1B_MASK },
- { AVR8_INT_T1COMPA, AVR8_REGIDX_TIMSK1, AVR8_TIMSK1_OCIE1A_MASK, AVR8_REGIDX_TIFR1, AVR8_TIFR1_OCF1A_MASK },
- { AVR8_INT_T1OVF, AVR8_REGIDX_TIMSK1, AVR8_TIMSK1_TOIE1_MASK, AVR8_REGIDX_TIFR1, AVR8_TIFR1_TOV1_MASK },
- { AVR8_INT_T2COMPB, AVR8_REGIDX_TIMSK2, AVR8_TIMSK2_OCIE2B_MASK, AVR8_REGIDX_TIFR2, AVR8_TIFR2_OCF2B_MASK },
- { AVR8_INT_T2COMPA, AVR8_REGIDX_TIMSK2, AVR8_TIMSK2_OCIE2A_MASK, AVR8_REGIDX_TIFR2, AVR8_TIFR2_OCF2A_MASK },
- { AVR8_INT_T2OVF, AVR8_REGIDX_TIMSK2, AVR8_TIMSK2_TOIE2_MASK, AVR8_REGIDX_TIFR2, AVR8_TIFR2_TOV2_MASK }
-};
-
-void avr8_device::update_interrupt(int source)
+void avr8_base_device::update_interrupt(int source)
{
const interrupt_condition &condition = s_int_conditions[source];
@@ -1146,19 +1350,19 @@ void atmega328_device::update_interrupt(int source)
}
}
-static const interrupt_condition s_mega644_int_conditions[AVR8_INTIDX_COUNT] =
+const avr8_base_device::interrupt_condition avr8_base_device::s_mega644_int_conditions[avr8_base_device::INTIDX_COUNT] =
{
- { ATMEGA644_INT_SPI_STC, AVR8_REGIDX_SPCR, AVR8_SPCR_SPIE_MASK, AVR8_REGIDX_SPSR, AVR8_SPSR_SPIF_MASK },
- { ATMEGA644_INT_T0COMPB, AVR8_REGIDX_TIMSK0, AVR8_TIMSK0_OCIE0B_MASK, AVR8_REGIDX_TIFR0, AVR8_TIFR0_OCF0B_MASK },
- { ATMEGA644_INT_T0COMPA, AVR8_REGIDX_TIMSK0, AVR8_TIMSK0_OCIE0A_MASK, AVR8_REGIDX_TIFR0, AVR8_TIFR0_OCF0A_MASK },
- { ATMEGA644_INT_T0OVF, AVR8_REGIDX_TIMSK0, AVR8_TIMSK0_TOIE0_MASK, AVR8_REGIDX_TIFR0, AVR8_TIFR0_TOV0_MASK },
- { ATMEGA644_INT_T1CAPT, AVR8_REGIDX_TIMSK1, AVR8_TIMSK1_ICIE1_MASK, AVR8_REGIDX_TIFR1, AVR8_TIFR1_ICF1_MASK },
- { ATMEGA644_INT_T1COMPB, AVR8_REGIDX_TIMSK1, AVR8_TIMSK1_OCIE1B_MASK, AVR8_REGIDX_TIFR1, AVR8_TIFR1_OCF1B_MASK },
- { ATMEGA644_INT_T1COMPA, AVR8_REGIDX_TIMSK1, AVR8_TIMSK1_OCIE1A_MASK, AVR8_REGIDX_TIFR1, AVR8_TIFR1_OCF1A_MASK },
- { ATMEGA644_INT_T1OVF, AVR8_REGIDX_TIMSK1, AVR8_TIMSK1_TOIE1_MASK, AVR8_REGIDX_TIFR1, AVR8_TIFR1_TOV1_MASK },
- { ATMEGA644_INT_T2COMPB, AVR8_REGIDX_TIMSK2, AVR8_TIMSK2_OCIE2B_MASK, AVR8_REGIDX_TIFR2, AVR8_TIFR2_OCF2B_MASK },
- { ATMEGA644_INT_T2COMPA, AVR8_REGIDX_TIMSK2, AVR8_TIMSK2_OCIE2A_MASK, AVR8_REGIDX_TIFR2, AVR8_TIFR2_OCF2A_MASK },
- { ATMEGA644_INT_T2OVF, AVR8_REGIDX_TIMSK2, AVR8_TIMSK2_TOIE2_MASK, AVR8_REGIDX_TIFR2, AVR8_TIFR2_TOV2_MASK }
+ { ATMEGA644_INT_SPI_STC, SPCR, SPCR_SPIE_MASK, SPSR, SPSR_SPIF_MASK },
+ { ATMEGA644_INT_T0COMPB, TIMSK0, TIMSK0_OCIE0B_MASK, TIFR0, TIFR0_OCF0B_MASK },
+ { ATMEGA644_INT_T0COMPA, TIMSK0, TIMSK0_OCIE0A_MASK, TIFR0, TIFR0_OCF0A_MASK },
+ { ATMEGA644_INT_T0OVF, TIMSK0, TIMSK0_TOIE0_MASK, TIFR0, TIFR0_TOV0_MASK },
+ { ATMEGA644_INT_T1CAPT, TIMSK1, TIMSK1_ICIE1_MASK, TIFR1, TIFR1_ICF1_MASK },
+ { ATMEGA644_INT_T1COMPB, TIMSK1, TIMSK1_OCIE1B_MASK, TIFR1, TIFR1_OCF1B_MASK },
+ { ATMEGA644_INT_T1COMPA, TIMSK1, TIMSK1_OCIE1A_MASK, TIFR1, TIFR1_OCF1A_MASK },
+ { ATMEGA644_INT_T1OVF, TIMSK1, TIMSK1_TOIE1_MASK, TIFR1, TIFR1_TOV1_MASK },
+ { ATMEGA644_INT_T2COMPB, TIMSK2, TIMSK2_OCIE2B_MASK, TIFR2, TIFR2_OCF2B_MASK },
+ { ATMEGA644_INT_T2COMPA, TIMSK2, TIMSK2_OCIE2A_MASK, TIFR2, TIFR2_OCF2A_MASK },
+ { ATMEGA644_INT_T2OVF, TIMSK2, TIMSK2_TOIE2_MASK, TIFR2, TIFR2_TOV2_MASK }
};
void atmega644_device::update_interrupt(int source)
@@ -1186,6 +1390,7 @@ void atmega1280_device::update_interrupt(int source)
if (m_r[condition.m_intreg] & condition.m_intmask)
intstate = (m_r[condition.m_regindex] & condition.m_regmask) ? 1 : 0;
+ if (intstate) logerror("interrupt %d is 1\n", source);
set_irq_line(condition.m_intindex << 1, intstate);
if (intstate)
@@ -1203,6 +1408,7 @@ void atmega2560_device::update_interrupt(int source)
if (m_r[condition.m_intreg] & condition.m_intmask)
intstate = (m_r[condition.m_regindex] & condition.m_regmask) ? 1 : 0;
+ if (intstate) logerror("interrupt %d is 1\n", source);
set_irq_line(condition.m_intindex << 1, intstate);
if (intstate)
@@ -1213,446 +1419,515 @@ void atmega2560_device::update_interrupt(int source)
//**************************************************************************
-// REGISTER HANDLING
+// PERIPHERAL HANDLING
//**************************************************************************
-void avr8_device::timer_tick()
-{
- for (int count = 0; count < m_opcycles; count++)
- {
- if (m_spi_active && m_spi_prescale > 0 && m_spi_prescale_countdown >= 0)
- {
- m_spi_prescale_count++;
- if (m_spi_prescale_count >= m_spi_prescale)
- {
- uint8_t out_bit = (m_r[AVR8_REGIDX_SPDR] & (1 << m_spi_prescale_countdown)) >> m_spi_prescale_countdown;
- m_spi_prescale_countdown--;
- m_io->write_byte(AVR8_IO_PORTB, (m_r[AVR8_REGIDX_PORTB] &~ AVR8_PORTB_MOSI) | (out_bit ? AVR8_PORTB_MOSI : 0));
- m_r[AVR8_REGIDX_PORTB] = (m_r[AVR8_REGIDX_PORTB] &~ AVR8_PORTB_MOSI) | (out_bit ? AVR8_PORTB_MOSI : 0);
- m_spi_prescale_count -= m_spi_prescale;
- }
- }
- for (int t = 0; t < m_num_timers; t++)
- {
- if (m_timer_prescale[t] != 0)
- {
- m_timer_prescale_count[t]++;
- if (m_timer_prescale_count[t] >= m_timer_prescale[t])
- {
- switch (t)
- {
- case 0: timer0_tick(); break;
- case 1: timer1_tick(); break;
- case 2: timer2_tick(); break;
- case 3: timer3_tick(); break;
- case 4: timer4_tick(); break;
- case 5: timer5_tick(); break;
- }
- m_timer_prescale_count[t] -= m_timer_prescale[t];
- }
- }
- }
- }
+template <int NumTimers>
+void avr8_device<NumTimers>::spi_tick()
+{
+ const uint8_t out_bit = (m_r[SPDR] & (1 << m_spi_prescale_countdown)) >> m_spi_prescale_countdown;
+ m_spi_prescale_countdown--;
+ const uint8_t data = (m_r[PORTB] &~ PORTB_MOSI) | (out_bit ? PORTB_MOSI : 0);
+ m_r[PORTB] = data;
+ m_gpio_out_cb[GPIOB](data);
+ m_r[PORTB] = (m_r[PORTB] &~ PORTB_MOSI) | (out_bit ? PORTB_MOSI : 0);
}
// Timer 0 Handling
-void avr8_device::timer0_tick()
+
+template <int NumTimers>
+void avr8_device<NumTimers>::timer0_tick_norm()
{
- static const uint8_t s_ocf0[2] = { (1 << AVR8_TIFR0_OCF0A_SHIFT), (1 << AVR8_TIFR0_OCF0B_SHIFT) };
- static const uint8_t s_int0[2] = { AVR8_INTIDX_OCF0A, AVR8_INTIDX_OCF0B };
+ LOGMASKED(LOG_TIMER0, "%s: WGM02_NORMAL: Unimplemented timer#0 waveform generation mode\n", machine().describe_context());
+ m_r[TCNT0]++;
+ m_timer_prescale_count[0] -= m_timer_prescale[0];
+}
- LOGMASKED(LOG_TIMER0_TICK, "%s: AVR8_WGM0: %d\n", machine().describe_context(), AVR8_WGM0);
- LOGMASKED(LOG_TIMER0_TICK, "%s: AVR8_TCCR0A_COM0B: %d\n", machine().describe_context(), AVR8_TCCR0A_COM0B);
+template <int NumTimers>
+void avr8_device<NumTimers>::timer0_tick_pwm_pc()
+{
+ LOGMASKED(LOG_TIMER0, "%s: WGM02_PWM_PC: Unimplemented timer#0 waveform generation mode\n", machine().describe_context());
+ m_r[TCNT0]++;
+ m_timer_prescale_count[0] -= m_timer_prescale[0];
+}
- uint8_t count = m_r[AVR8_REGIDX_TCNT0];
- count++;
+template <int NumTimers>
+void avr8_device<NumTimers>::timer0_tick_ctc_norm()
+{
+ static const uint8_t s_ocf0[2] = { (1 << TIFR0_OCF0A_SHIFT), (1 << TIFR0_OCF0B_SHIFT) };
+ static const uint8_t s_int0[2] = { INTIDX_OCF0A, INTIDX_OCF0B };
- switch (AVR8_WGM0)
+ if (m_r[TCNT0] == m_r[OCR0A] - 1)
{
- case WGM02_NORMAL:
- LOGMASKED(LOG_TIMER0, "%s: WGM02_NORMAL: Unimplemented timer#0 waveform generation mode\n", machine().describe_context());
- break;
-
- case WGM02_PWM_PC:
- LOGMASKED(LOG_TIMER0, "%s: WGM02_PWM_PC: Unimplemented timer0 waveform generation mode\n", machine().describe_context());
- break;
-
- case WGM02_CTC_CMP:
- switch (AVR8_TCCR0A_COM0B)
- {
- case 0: /* Normal Operation */
- if (count == AVR8_OCR0A)
- {
- m_r[AVR8_REGIDX_TIFR0] |= s_ocf0[AVR8_REG_A];
- update_interrupt(s_int0[AVR8_REG_A]);
- count = 0;
- }
- else if (count == AVR8_OCR0B)
- {
- m_r[AVR8_REGIDX_TIFR0] |= s_ocf0[AVR8_REG_B];
- update_interrupt(s_int0[AVR8_REG_B]);
- }
- break;
-
- case 1: /* Toggle OC0B on compare match */
- if (count == m_timer_top[0])
- {
- m_timer_top[0] = 0;
- LOGMASKED(LOG_TIMER0, "%s: timer0: Toggle OC0B on match\n", machine().describe_context());
- m_io->write_byte(AVR8_IO_PORTG, m_io->read_byte(AVR8_IO_PORTG) ^ (1 << 5));
- }
- break;
-
- case 2: /* Clear OC0B on compare match */
- if (count == m_timer_top[0])
- {
- m_timer_top[0] = 0;
- LOGMASKED(LOG_TIMER0, "[0] timer0: Clear OC0B on match\n", machine().describe_context());
- m_io->write_byte(AVR8_IO_PORTG, m_io->read_byte(AVR8_IO_PORTG) & ~(1 << 5));
- }
- break;
-
- case 3: /* Set OC0B on compare match */
- if (count == m_timer_top[0])
- {
- m_timer_top[0] = 0;
- LOGMASKED(LOG_TIMER0, "%s: timer0: Set OC0B on match\n", machine().describe_context());
- m_io->write_byte(AVR8_IO_PORTG, m_io->read_byte(AVR8_IO_PORTG) | (1 << 5));
- }
- break;
- }
- break;
-
- case WGM02_FAST_PWM:
- LOGMASKED(LOG_TIMER0 | LOG_UNKNOWN, "%s: WGM02_FAST_PWM: Unimplemented timer0 waveform generation mode\n", machine().describe_context());
- break;
-
- case WGM02_PWM_PC_CMP:
- LOGMASKED(LOG_TIMER0 | LOG_UNKNOWN, "%s: WGM02_PWM_PC_CMP: Unimplemented timer0 waveform generation mode\n", machine().describe_context());
- break;
-
- case WGM02_FAST_PWM_CMP:
- LOGMASKED(LOG_TIMER0 | LOG_UNKNOWN, "%s: WGM02_FAST_PWM_CMP: Unimplemented timer0 waveform generation mode\n", machine().describe_context());
- break;
-
- default:
- LOGMASKED(LOG_TIMER0 | LOG_UNKNOWN, "%s: update_timer0_compare_mode: Unknown waveform generation mode: %02x\n", machine().describe_context(), AVR8_WGM0);
- break;
+ m_r[TIFR0] |= s_ocf0[AVR8_REG_A];
+ update_interrupt(s_int0[AVR8_REG_A]);
+ m_r[TCNT0] = 0;
}
-
- m_r[AVR8_REGIDX_TCNT0] = count;
+ else if (m_r[TCNT0] == m_r[OCR0B] - 1)
+ {
+ m_r[TIFR0] |= s_ocf0[AVR8_REG_B];
+ update_interrupt(s_int0[AVR8_REG_B]);
+ m_r[TCNT0]++;
+ }
+ else
+ {
+ m_r[TCNT0]++;
+ }
+ m_timer_prescale_count[0] -= m_timer_prescale[0];
}
-void avr8_device::changed_tccr0a(uint8_t data)
+template <int NumTimers>
+void avr8_device<NumTimers>::timer0_tick_ctc_toggle()
{
- uint8_t oldtccr = AVR8_TCCR0A;
- uint8_t newtccr = data;
- uint8_t changed = newtccr ^ oldtccr;
-
- AVR8_TCCR0A = data;
-
- if (changed & AVR8_TCCR0A_WGM0_10_MASK)
+ if (m_r[TCNT0] == m_timer_top[0] - 1)
{
- update_timer_waveform_gen_mode(0, AVR8_WGM0);
+ m_timer_top[0] = 0;
+ LOGMASKED(LOG_TIMER0, "%s: timer0: Toggle OC0B on match\n", machine().describe_context());
+ m_r[PORTG] ^= (1 << 5);
+ m_gpio_out_cb[GPIOG](m_r[PORTG]);
}
+ m_r[TCNT0]++;
+ m_timer_prescale_count[0] -= m_timer_prescale[0];
}
-void avr8_device::timer0_force_output_compare(int reg)
+template <int NumTimers>
+void avr8_device<NumTimers>::timer0_tick_ctc_clear()
{
- LOGMASKED(LOG_TIMER0 | LOG_UNKNOWN, "%s: timer0_force_output_compare: TODO; should be forcing OC0%c\n", machine().describe_context(), avr8_reg_name[reg]);
+ if (m_r[TCNT0] == m_timer_top[0])
+ {
+ m_timer_top[0] = 0;
+ LOGMASKED(LOG_TIMER0, "[0] timer0: Clear OC0B on match\n", machine().describe_context());
+ m_r[PORTG] &= ~(1 << 5);
+ m_gpio_out_cb[GPIOG](m_r[PORTG]);
+ }
+ m_r[TCNT0]++;
+ m_timer_prescale_count[0] -= m_timer_prescale[0];
}
-void avr8_device::changed_tccr0b(uint8_t data)
+template <int NumTimers>
+void avr8_device<NumTimers>::timer0_tick_ctc_set()
{
- LOGMASKED(LOG_TIMER0, "%s: changed_tccr0b: data = 0x%02X\n", machine().describe_context(), data);
-
- uint8_t oldtccr = AVR8_TCCR0B;
- uint8_t newtccr = data;
- uint8_t changed = newtccr ^ oldtccr;
-
- AVR8_TCCR0B = data;
-
- if (changed & AVR8_TCCR0B_FOC0A_MASK)
+ if (m_r[TCNT0] == m_timer_top[0])
{
- // TODO
- timer0_force_output_compare(AVR8_REG_A);
+ m_timer_top[0] = 0;
+ LOGMASKED(LOG_TIMER0, "%s: timer0: Set OC0B on match\n", machine().describe_context());
+ m_r[PORTG] |= (1 << 5);
+ m_gpio_out_cb[GPIOG](m_r[PORTG]);
}
+ m_r[TCNT0]++;
+ m_timer_prescale_count[0] -= m_timer_prescale[0];
+}
- if (changed & AVR8_TCCR0B_FOC0B_MASK)
- {
- // TODO
- timer0_force_output_compare(AVR8_REG_B);
- }
+template <int NumTimers>
+void avr8_device<NumTimers>::timer0_tick_fast_pwm()
+{
+ LOGMASKED(LOG_TIMER0 | LOG_UNKNOWN, "%s: WGM02_FAST_PWM: Unimplemented timer0 waveform generation mode\n", machine().describe_context());
+ m_r[TCNT0]++;
+ m_timer_prescale_count[0] -= m_timer_prescale[0];
+}
- if (changed & AVR8_TCCR0B_WGM0_2_MASK)
- {
- update_timer_waveform_gen_mode(0, AVR8_WGM0);
- }
+template <int NumTimers>
+void avr8_device<NumTimers>::timer0_tick_pwm_pc_cmp()
+{
+ LOGMASKED(LOG_TIMER0 | LOG_UNKNOWN, "%s: WGM02_PWM_PC_CMP: Unimplemented timer0 waveform generation mode\n", machine().describe_context());
+ m_r[TCNT0]++;
+ m_timer_prescale_count[0] -= m_timer_prescale[0];
+}
- if (changed & AVR8_TCCR0B_CS_MASK)
- {
- update_timer_clock_source(0, AVR8_TIMER0_CLOCK_SELECT);
- }
+template <int NumTimers>
+void avr8_device<NumTimers>::timer0_tick_fast_pwm_cmp()
+{
+ LOGMASKED(LOG_TIMER0 | LOG_UNKNOWN, "%s: WGM02_FAST_PWM_CMP: Unimplemented timer0 waveform generation mode\n", machine().describe_context());
+ m_r[TCNT0]++;
+ m_timer_prescale_count[0] -= m_timer_prescale[0];
}
-void avr8_device::update_ocr0(uint8_t newval, uint8_t reg)
+template <int NumTimers>
+void avr8_device<NumTimers>::timer0_tick_default()
{
- m_r[(reg == AVR8_REG_A) ? AVR8_REGIDX_OCR0A : AVR8_REGIDX_OCR0B] = newval;
+ LOGMASKED(LOG_TIMER0 | LOG_UNKNOWN, "%s: timer0_tick_default: Unknown waveform generation mode: %02x\n", machine().describe_context(), WGM0);
+ m_r[TCNT0]++;
+ m_timer_prescale_count[0] -= m_timer_prescale[0];
}
-// Timer 1 Handling
+template <int NumTimers>
+void avr8_device<NumTimers>::timer0_force_output_compare(int reg)
+{
+ LOGMASKED(LOG_TIMER0 | LOG_UNKNOWN, "%s: timer0_force_output_compare: TODO; should be forcing OC0%c\n", machine().describe_context(), 'A' + reg);
+ m_timer_prescale_count[0] -= m_timer_prescale[0];
+}
-inline void avr8_device::timer1_tick()
+template <int NumTimers>
+void avr8_device<NumTimers>::update_ocr0(uint8_t newval, uint8_t reg)
{
- /* TODO: Handle comparison, setting OC1A pin, detection of BOTTOM and TOP */
+ m_r[(reg == AVR8_REG_A) ? OCR0A : OCR0B] = newval;
+}
- static const uint8_t s_ocf1[2] = { (1 << AVR8_TIFR1_OCF1A_SHIFT), (1 << AVR8_TIFR1_OCF1B_SHIFT) };
- static const uint8_t s_int1[2] = { AVR8_INTIDX_OCF1A, AVR8_INTIDX_OCF1B };
- const uint16_t icr1 = AVR8_ICR1;
- int32_t increment = m_timer_increment[1];
+// Timer 1 Handling
- for (int32_t reg = AVR8_REG_A; reg <= AVR8_REG_B; reg++)
+template <int NumTimers>
+template <int TimerMode, int ChannelModeA, int ChannelModeB>
+inline void avr8_device<NumTimers>::timer1_tick()
+{
+ static const uint8_t s_ocf1[2] = { (1 << TIFR1_OCF1A_SHIFT), (1 << TIFR1_OCF1B_SHIFT) };
+ static const uint8_t s_int1[2] = { INTIDX_OCF1A, INTIDX_OCF1B };
+ const uint16_t icr1 = ICR1;
+ uint16_t timer1_count = (m_r[TCNT1H] << 8) | m_r[TCNT1L];
+ int32_t increment = 1;
+
+ switch (TimerMode)
{
- switch (m_wgm1)
+ case WGM1_CTC_OCR:
+ if (timer1_count == 0xffff)
+ {
+ LOGMASKED(LOG_TIMER1_TICK, "%s: timer1 WGM1 CTC_OCR, TOP, new count %04x, OCR1A/B %04x/%04x, ICR1 %04x\n", machine().describe_context(), timer1_count, m_ocr1[AVR8_REG_A], m_ocr1[AVR8_REG_B], icr1);
+ m_r[TIFR1] |= TIFR1_TOV1_MASK;
+ update_interrupt(INTIDX_TOV1);
+ timer1_count = 0;
+ increment = 0;
+ }
+
+ if (timer1_count == m_ocr1[AVR8_REG_A])
{
- case WGM1_CTC_OCR:
- LOGMASKED(LOG_TIMER1_TICK, "%s: timer1_count: %04x\n", machine().describe_context(), m_timer1_count);
- LOGMASKED(LOG_TIMER1_TICK, "%s: OCR1%c: %04x\n", machine().describe_context(), reg ? 'A' : 'B', m_ocr1[reg]);
- if (m_timer1_count == 0xffff)
+ LOGMASKED(LOG_TIMER1_TICK, "%s: timer1 WGM1 CTC_OCR, OCR1A, new count %04x, OCR1A/B %04x/%04x, ICR1 %04x\n", machine().describe_context(), timer1_count, m_ocr1[AVR8_REG_A], m_ocr1[AVR8_REG_B], icr1);
+ timer1_count = 0;
+ increment = 0;
+
+ switch (ChannelModeA)
{
- m_r[AVR8_REGIDX_TIFR1] |= AVR8_TIFR1_TOV1_MASK;
- update_interrupt(AVR8_INTIDX_TOV1);
- m_timer1_count = 0;
- increment = 0;
+ case 0: /* Normal Operation; OC1A/B disconnected */
+ break;
+
+ case 1: /* Toggle OC1A on compare match */
+ LOGMASKED(LOG_TIMER1, "%s: timer1: Toggle OC1A on match\n", machine().describe_context());
+ m_r[PORTB] ^= 2;
+ m_gpio_out_cb[GPIOB](m_r[PORTB]);
+ break;
+
+ case 2: /* Clear OC1A/B on compare match */
+ LOGMASKED(LOG_TIMER1, "%s: timer1: Clear OC1A on match\n", machine().describe_context());
+ m_r[PORTB] &= ~(2 << AVR8_REG_A);
+ m_gpio_out_cb[GPIOB](m_r[PORTB]);
+ break;
+
+ case 3: /* Set OC1A/B on compare match */
+ LOGMASKED(LOG_TIMER1, "%s: timer1: Set OC1A on match\n", machine().describe_context());
+ m_r[PORTB] |= 2 << AVR8_REG_A;
+ m_gpio_out_cb[GPIOB](m_r[PORTB]);
+ break;
}
- if (m_timer1_count == m_ocr1[reg])
+ m_r[TIFR1] |= s_ocf1[AVR8_REG_A];
+ update_interrupt(s_int1[AVR8_REG_A]);
+ }
+ else if (timer1_count == 0)
+ {
+ LOGMASKED(LOG_TIMER1_TICK, "%s: timer1 WGM1 CTC_OCR, BOTTOM, new count %04x, OCR1A/B %04x/%04x, ICR1 %04x\n", machine().describe_context(), timer1_count, m_ocr1[AVR8_REG_A], m_ocr1[AVR8_REG_B], icr1);
+ m_r[TIFR1] &= ~TIFR1_TOV1_MASK;
+ update_interrupt(INTIDX_TOV1);
+ }
+
+ if (timer1_count == m_ocr1[AVR8_REG_B])
+ {
+ LOGMASKED(LOG_TIMER1_TICK, "%s: timer1 WGM1 CTC_OCR, OCR1B, new count %04x, OCR1A/B %04x/%04x, ICR1 %04x\n", machine().describe_context(), timer1_count, m_ocr1[AVR8_REG_A], m_ocr1[AVR8_REG_B], icr1);
+ switch (ChannelModeB)
{
- if (reg == 0)
- {
- m_timer1_count = 0;
- increment = 0;
- }
+ case 0: /* Normal Operation; OC1A/B disconnected */
+ case 1: /* Toggle OC1A on compare match */
+ break;
+
+ case 2: /* Clear OC1A/B on compare match */
+ LOGMASKED(LOG_TIMER1, "%s: timer1: Clear OC1B on match\n", machine().describe_context());
+ m_r[PORTB] &= ~(2 << AVR8_REG_B);
+ m_gpio_out_cb[GPIOB](m_r[PORTB]);
+ break;
+
+ case 3: /* Set OC1A/B on compare match */
+ LOGMASKED(LOG_TIMER1, "%s: timer1: Set OC1B on match\n", machine().describe_context());
+ m_r[PORTB] |= 2 << AVR8_REG_B;
+ m_gpio_out_cb[GPIOB](m_r[PORTB]);
+ break;
+ }
- switch (m_timer1_compare_mode[reg] & 3)
- {
- case 0: /* Normal Operation; OC1A/B disconnected */
- break;
+ m_r[TIFR1] |= s_ocf1[AVR8_REG_B];
+ update_interrupt(s_int1[AVR8_REG_B]);
+ }
+ break;
- case 1: /* Toggle OC1A on compare match */
- if (reg == 0)
- {
- LOGMASKED(LOG_TIMER1, "%s: timer1: Toggle OC1%c on match\n", machine().describe_context());
- m_io->write_byte(AVR8_IO_PORTB, m_io->read_byte(AVR8_IO_PORTB) ^ (2 << reg));
- }
- break;
+ case WGM1_FAST_PWM_OCR:
+ if (timer1_count == m_ocr1[AVR8_REG_A])
+ {
+ LOGMASKED(LOG_TIMER1_TICK, "%s: timer1 WGM1 FAST_PWM_OCR, OCR1A, new count %04x, OCR1A/B %04x/%04x, ICR1 %04x\n", machine().describe_context(), timer1_count, m_ocr1[AVR8_REG_A], m_ocr1[AVR8_REG_B], icr1);
+ m_r[TIFR1] |= TIFR1_TOV1_MASK;
+ update_interrupt(INTIDX_TOV1);
+ timer1_count = 0;
+ increment = 0;
- case 2: /* Clear OC1A/B on compare match */
- LOGMASKED(LOG_TIMER1, "%s: timer1: Clear OC1%c on match\n", machine().describe_context(), reg ? 'B' : 'A');
- m_io->write_byte(AVR8_IO_PORTB, m_io->read_byte(AVR8_IO_PORTB) & ~(2 << reg));
- break;
+ switch (ChannelModeA)
+ {
+ case 0: /* Normal Operation; OC1A/B disconnected */
+ break;
+
+ case 1: /* Toggle OC1A on compare match */
+ LOGMASKED(LOG_TIMER1, "%s: timer1: Toggle OC1A on match\n", machine().describe_context());
+ m_r[PORTB] ^= 2;
+ m_gpio_out_cb[GPIOB](m_r[PORTB]);
+ break;
+
+ case 2: /* Clear OC1A/B on compare match */
+ LOGMASKED(LOG_TIMER1, "%s: timer1: Clear OC1A on match\n", machine().describe_context());
+ m_r[PORTB] &= ~(2 << AVR8_REG_A);
+ m_gpio_out_cb[GPIOB](m_r[PORTB]);
+ break;
+
+ case 3: /* Set OC1A/B on compare match */
+ LOGMASKED(LOG_TIMER1, "%s: timer1: Set OC1A on match\n", machine().describe_context());
+ m_r[PORTB] |= 2 << AVR8_REG_A;
+ m_gpio_out_cb[GPIOB](m_r[PORTB]);
+ break;
+ }
- case 3: /* Set OC1A/B on compare match */
- LOGMASKED(LOG_TIMER1, "%s: timer1: Set OC1%c on match\n", machine().describe_context(), reg ? 'B' : 'A');
- m_io->write_byte(AVR8_IO_PORTB, m_io->read_byte(AVR8_IO_PORTB) | (2 << reg));
- break;
- }
+ m_r[TIFR1] |= s_ocf1[AVR8_REG_A];
+ update_interrupt(s_int1[AVR8_REG_A]);
+ }
+ else if (timer1_count == 0)
+ {
+ LOGMASKED(LOG_TIMER1_TICK, "%s: timer1 WGM1 FAST_PWM_OCR, BOTTOM A, new count %04x, OCR1A/B %04x/%04x, ICR1 %04x\n", machine().describe_context(), timer1_count, m_ocr1[AVR8_REG_A], m_ocr1[AVR8_REG_B], icr1);
+ m_r[TIFR1] &= ~TIFR1_TOV1_MASK;
+ update_interrupt(INTIDX_TOV1);
- m_r[AVR8_REGIDX_TIFR1] |= s_ocf1[reg];
- update_interrupt(s_int1[reg]);
- }
- else if (m_timer1_count == 0)
+ switch (ChannelModeA)
{
- if (reg == 0)
- {
- m_r[AVR8_REGIDX_TIFR1] &= ~AVR8_TIFR1_TOV1_MASK;
- update_interrupt(AVR8_INTIDX_TOV1);
- }
+ case 0: /* Normal Operation; OC1A/B disconnected */
+ break;
+
+ case 1: /* Toggle OC1A at BOTTOM*/
+ LOGMASKED(LOG_TIMER1, "%s: timer1: Toggle OC1A at BOTTOM\n", machine().describe_context());
+ m_r[PORTB] ^= 2;
+ m_gpio_out_cb[GPIOB](m_r[PORTB]);
+ break;
+
+ case 2: /* Set OC1A/B at BOTTOM*/
+ LOGMASKED(LOG_TIMER1, "%s: timer1: Set OC1A at BOTTOM\n", machine().describe_context());
+ m_r[PORTB] |= 2 << AVR8_REG_A;
+ m_gpio_out_cb[GPIOB](m_r[PORTB]);
+ break;
+
+ case 3: /* Clear OC1A/B at BOTTOM */
+ LOGMASKED(LOG_TIMER1, "%s: timer1: Clear OC1A at BOTTOM\n", machine().describe_context());
+ m_r[PORTB] &= ~(2 << AVR8_REG_A);
+ m_gpio_out_cb[GPIOB](m_r[PORTB]);
+ break;
}
- break;
+ }
- case WGM1_FAST_PWM_OCR:
- if (m_timer1_count == m_ocr1[reg])
+ if (timer1_count == m_ocr1[AVR8_REG_B])
+ {
+ LOGMASKED(LOG_TIMER1_TICK, "%s: timer1 WGM1 FAST_PWM_OCR, OCR1B, new count %04x, OCR1A/B %04x/%04x, ICR1 %04x\n", machine().describe_context(), timer1_count, m_ocr1[AVR8_REG_A], m_ocr1[AVR8_REG_B], icr1);
+ switch (ChannelModeB)
{
- if (reg == 0)
- {
- m_r[AVR8_REGIDX_TIFR1] |= AVR8_TIFR1_TOV1_MASK;
- update_interrupt(AVR8_INTIDX_TOV1);
- m_timer1_count = 0;
- increment = 0;
- }
-
- switch (m_timer1_compare_mode[reg] & 3)
- {
- case 0: /* Normal Operation; OC1A/B disconnected */
- break;
-
- case 1: /* Toggle OC1A on compare match */
- if (reg == 0)
- {
- LOGMASKED(LOG_TIMER1, "%s: timer1: Toggle OC1%c on match\n", machine().describe_context());
- m_io->write_byte(AVR8_IO_PORTB, m_io->read_byte(AVR8_IO_PORTB) ^ (2 << reg));
- }
- break;
-
- case 2: /* Clear OC1A/B on compare match */
- LOGMASKED(LOG_TIMER1, "%s: timer1: Clear OC1%c on match\n", machine().describe_context(), reg ? 'B' : 'A');
- m_io->write_byte(AVR8_IO_PORTB, m_io->read_byte(AVR8_IO_PORTB) & ~(2 << reg));
- break;
-
- case 3: /* Set OC1A/B on compare match */
- LOGMASKED(LOG_TIMER1, "%s: timer1: Set OC1%c on match\n", machine().describe_context(), reg ? 'B' : 'A');
- m_io->write_byte(AVR8_IO_PORTB, m_io->read_byte(AVR8_IO_PORTB) | (2 << reg));
- break;
- }
-
- m_r[AVR8_REGIDX_TIFR1] |= s_ocf1[reg];
- update_interrupt(s_int1[reg]);
+ case 0: /* Normal Operation; OC1A/B disconnected */
+ case 1: /* Toggle OC1A on compare match */
+ break;
+
+ case 2: /* Clear OC1A/B on compare match */
+ LOGMASKED(LOG_TIMER1, "%s: timer1: Clear OC1B on match\n", machine().describe_context());
+ m_r[PORTB] &= ~(2 << AVR8_REG_B);
+ m_gpio_out_cb[GPIOB](m_r[PORTB]);
+ break;
+
+ case 3: /* Set OC1A/B on compare match */
+ LOGMASKED(LOG_TIMER1, "%s: timer1: Set OC1B on match\n", machine().describe_context());
+ m_r[PORTB] |= 2 << AVR8_REG_B;
+ m_gpio_out_cb[GPIOB](m_r[PORTB]);
+ break;
}
- else if (m_timer1_count == 0)
- {
- if (reg == 0)
- {
- m_r[AVR8_REGIDX_TIFR1] &= ~AVR8_TIFR1_TOV1_MASK;
- update_interrupt(AVR8_INTIDX_TOV1);
- }
-
- switch (m_timer1_compare_mode[reg] & 3)
- {
- case 0: /* Normal Operation; OC1A/B disconnected */
- break;
- case 1: /* Toggle OC1A at BOTTOM*/
- if (reg == 0)
- {
- LOGMASKED(LOG_TIMER1, "%s: timer1: Toggle OC1A at BOTTOM\n", machine().describe_context());
- m_io->write_byte(AVR8_IO_PORTB, m_io->read_byte(AVR8_IO_PORTB) ^ (2 << reg));
- }
- break;
-
- case 2: /* Set OC1A/B at BOTTOM*/
- LOGMASKED(LOG_TIMER1, "%s: timer1: Set OC1%c at BOTTOM\n", machine().describe_context(), reg ? 'B' : 'A');
- m_io->write_byte(AVR8_IO_PORTB, m_io->read_byte(AVR8_IO_PORTB) | (2 << reg));
- break;
-
- case 3: /* Clear OC1A/B at BOTTOM */
- LOGMASKED(LOG_TIMER1, "%s: timer1: Clear OC1%c at BOTTOM\n", machine().describe_context(), reg ? 'B' : 'A');
- m_io->write_byte(AVR8_IO_PORTB, m_io->read_byte(AVR8_IO_PORTB) & ~(2 << reg));
- break;
- }
+ m_r[TIFR1] |= s_ocf1[AVR8_REG_B];
+ update_interrupt(s_int1[AVR8_REG_B]);
+ }
+ else if (timer1_count == 0)
+ {
+ LOGMASKED(LOG_TIMER1_TICK, "%s: timer1 WGM1 FAST_PWM_OCR, BOTTOM B, new count %04x, OCR1A/B %04x/%04x, ICR1 %04x\n", machine().describe_context(), timer1_count, m_ocr1[AVR8_REG_A], m_ocr1[AVR8_REG_B], icr1);
+ switch (ChannelModeB)
+ {
+ case 0: /* Normal Operation; OC1A/B disconnected */
+ case 1: /* Toggle OC1A at BOTTOM*/
+ break;
+
+ case 2: /* Set OC1A/B at BOTTOM*/
+ LOGMASKED(LOG_TIMER1, "%s: timer1: Set OC1B at BOTTOM\n", machine().describe_context());
+ m_r[PORTB] |= 2 << AVR8_REG_B;
+ m_gpio_out_cb[GPIOB](m_r[PORTB]);
+ break;
+
+ case 3: /* Clear OC1A/B at BOTTOM */
+ LOGMASKED(LOG_TIMER1, "%s: timer1: Clear OC1B at BOTTOM\n", machine().describe_context());
+ m_r[PORTB] &= ~(2 << AVR8_REG_B);
+ m_gpio_out_cb[GPIOB](m_r[PORTB]);
+ break;
}
- break;
+ }
+ break;
- case WGM1_FAST_PWM_ICR:
- if (m_timer1_count == m_ocr1[reg])
+ case WGM1_FAST_PWM_ICR:
+ if (timer1_count == m_ocr1[AVR8_REG_A])
+ {
+ LOGMASKED(LOG_TIMER1_TICK, "%s: timer1 WGM1 FAST_PWM_ICR, OCR1A, new count %04x, OCR1A/B %04x/%04x, ICR1 %04x\n", machine().describe_context(), timer1_count, m_ocr1[AVR8_REG_A], m_ocr1[AVR8_REG_B], icr1);
+ switch (ChannelModeA)
{
- switch (m_timer1_compare_mode[reg] & 3)
- {
- case 0: /* Normal Operation; OC1A/B disconnected */
- break;
-
- case 1: /* Toggle OC1A on compare match */
- if (reg == 0)
- {
- LOGMASKED(LOG_TIMER1, "%s: timer1: Toggle OC1%c on match\n", machine().describe_context());
- m_io->write_byte(AVR8_IO_PORTB, m_io->read_byte(AVR8_IO_PORTB) ^ (2 << reg));
- }
- break;
-
- case 2: /* Clear OC1A/B on compare match */
- LOGMASKED(LOG_TIMER1, "%s: timer1: Clear OC1%c on match\n", machine().describe_context(), reg ? 'B' : 'A');
- m_io->write_byte(AVR8_IO_PORTB, m_io->read_byte(AVR8_IO_PORTB) & ~(2 << reg));
- break;
-
- case 3: /* Set OC1A/B on compare match */
- LOGMASKED(LOG_TIMER1, "%s: timer1: Set OC1%c on match\n", machine().describe_context(), reg ? 'B' : 'A');
- m_io->write_byte(AVR8_IO_PORTB, m_io->read_byte(AVR8_IO_PORTB) | (2 << reg));
- break;
- }
-
- m_r[AVR8_REGIDX_TIFR1] |= s_ocf1[reg];
- update_interrupt(s_int1[reg]);
+ case 0: /* Normal Operation; OC1A/B disconnected */
+ break;
+
+ case 1: /* Toggle OC1A on compare match */
+ LOGMASKED(LOG_TIMER1, "%s: timer1: Toggle OC1A on match\n", machine().describe_context());
+ m_r[PORTB] ^= 2;
+ m_gpio_out_cb[GPIOB](m_r[PORTB]);
+ break;
+
+ case 2: /* Clear OC1A/B on compare match */
+ LOGMASKED(LOG_TIMER1, "%s: timer1: Clear OC1A on match\n", machine().describe_context());
+ m_r[PORTB] &= ~(2 << AVR8_REG_A);
+ m_gpio_out_cb[GPIOB](m_r[PORTB]);
+ break;
+
+ case 3: /* Set OC1A/B on compare match */
+ LOGMASKED(LOG_TIMER1, "%s: timer1: Set OC1A on match\n", machine().describe_context());
+ m_r[PORTB] |= 2 << AVR8_REG_A;
+ m_gpio_out_cb[GPIOB](m_r[PORTB]);
+ break;
}
- else if (m_timer1_count == 0)
- {
- if (reg == 0)
- {
- m_r[AVR8_REGIDX_TIFR1] &= ~AVR8_TIFR1_TOV1_MASK;
- update_interrupt(AVR8_INTIDX_TOV1);
- }
- switch (m_timer1_compare_mode[reg] & 3)
- {
- case 0: /* Normal Operation; OC1A/B disconnected */
- break;
-
- case 1: /* Toggle OC1A at BOTTOM*/
- if (reg == 0)
- {
- LOGMASKED(LOG_TIMER1, "%s: timer1: Toggle OC1A at BOTTOM\n", machine().describe_context());
- m_io->write_byte(AVR8_IO_PORTB, m_io->read_byte(AVR8_IO_PORTB) ^ (2 << reg));
- }
- break;
+ m_r[TIFR1] |= s_ocf1[AVR8_REG_A];
+ update_interrupt(s_int1[AVR8_REG_A]);
+ }
+ else if (timer1_count == 0)
+ {
+ LOGMASKED(LOG_TIMER1_TICK, "%s: timer1 WGM1 FAST_PWM_ICR, BOTTOM A, new count %04x, OCR1A/B %04x/%04x, ICR1 %04x\n", machine().describe_context(), timer1_count, m_ocr1[AVR8_REG_A], m_ocr1[AVR8_REG_B], icr1);
+ m_r[TIFR1] &= ~TIFR1_TOV1_MASK;
+ update_interrupt(INTIDX_TOV1);
- case 2: /* Set OC1A/B at BOTTOM*/
- LOGMASKED(LOG_TIMER1, "%s: timer1: Set OC1%c at BOTTOM\n", machine().describe_context(), reg ? 'B' : 'A');
- m_io->write_byte(AVR8_IO_PORTB, m_io->read_byte(AVR8_IO_PORTB) | (2 << reg));
- break;
+ switch (ChannelModeA)
+ {
+ case 0: /* Normal Operation; OC1A/B disconnected */
+ break;
+
+ case 1: /* Toggle OC1A at BOTTOM*/
+ LOGMASKED(LOG_TIMER1, "%s: timer1: Toggle OC1A at BOTTOM\n", machine().describe_context());
+ m_r[PORTB] ^= 2;
+ m_gpio_out_cb[GPIOB](m_r[PORTB]);
+ break;
+
+ case 2: /* Set OC1A/B at BOTTOM*/
+ LOGMASKED(LOG_TIMER1, "%s: timer1: Set OC1A at BOTTOM\n", machine().describe_context());
+ m_r[PORTB] |= 2 << AVR8_REG_A;
+ m_gpio_out_cb[GPIOB](m_r[PORTB]);
+ break;
+
+ case 3: /* Clear OC1A/B at BOTTOM */
+ LOGMASKED(LOG_TIMER1, "%s: timer1: Clear OC1A at BOTTOM\n", machine().describe_context());
+ m_r[PORTB] &= ~(2 << AVR8_REG_A);
+ m_gpio_out_cb[GPIOB](m_r[PORTB]);
+ break;
+ }
+ }
- case 3: /* Clear OC1A/B at BOTTOM */
- LOGMASKED(LOG_TIMER1, "%s: timer1: Clear OC1%c at BOTTOM\n", machine().describe_context(), reg ? 'B' : 'A');
- m_io->write_byte(AVR8_IO_PORTB, m_io->read_byte(AVR8_IO_PORTB) & ~(2 << reg));
- break;
- }
+ if (timer1_count == m_ocr1[AVR8_REG_B])
+ {
+ switch (ChannelModeB)
+ {
+ case 0: /* Normal Operation; OC1A/B disconnected */
+ case 1: /* Toggle OC1A on compare match */
+ break;
+
+ case 2: /* Clear OC1A/B on compare match */
+ LOGMASKED(LOG_TIMER1, "%s: timer1: Clear OC1B on match\n", machine().describe_context());
+ m_r[PORTB] &= ~(2 << AVR8_REG_B);
+ m_gpio_out_cb[GPIOB](m_r[PORTB]);
+ break;
+
+ case 3: /* Set OC1A/B on compare match */
+ LOGMASKED(LOG_TIMER1, "%s: timer1: Set OC1B on match\n", machine().describe_context());
+ m_r[PORTB] |= 2 << AVR8_REG_B;
+ m_gpio_out_cb[GPIOB](m_r[PORTB]);
+ break;
}
- if (m_timer1_count == icr1 && reg == 1)
+ m_r[TIFR1] |= s_ocf1[AVR8_REG_B];
+ update_interrupt(s_int1[AVR8_REG_B]);
+ }
+ else if (timer1_count == 0)
+ {
+ switch (ChannelModeB)
{
- m_r[AVR8_REGIDX_TIFR1] |= AVR8_TIFR1_TOV1_MASK;
- update_interrupt(AVR8_INTIDX_TOV1);
- m_timer1_count = 0;
- increment = 0;
+ case 0: /* Normal Operation; OC1A/B disconnected */
+ case 1: /* Toggle OC1A at BOTTOM*/
+ break;
+
+ case 2: /* Set OC1A/B at BOTTOM*/
+ LOGMASKED(LOG_TIMER1, "%s: timer1: Set OC1B at BOTTOM\n", machine().describe_context());
+ m_r[PORTB] |= 2 << AVR8_REG_B;
+ m_gpio_out_cb[GPIOB](m_r[PORTB]);
+ break;
+
+ case 3: /* Clear OC1A/B at BOTTOM */
+ LOGMASKED(LOG_TIMER1, "%s: timer1: Clear OC1B at BOTTOM\n", machine().describe_context());
+ m_r[PORTB] &= ~(2 << AVR8_REG_B);
+ m_gpio_out_cb[GPIOB](m_r[PORTB]);
+ break;
}
- break;
+ }
- default:
- LOGMASKED(LOG_TIMER1 | LOG_UNKNOWN, "%s: timer1_tick: Unknown waveform generation mode: %02x\n", machine().describe_context(), m_wgm1);
- break;
+ if (timer1_count == icr1)
+ {
+ m_r[TIFR1] |= TIFR1_TOV1_MASK;
+ update_interrupt(INTIDX_TOV1);
+ timer1_count = 0;
+ increment = 0;
}
+ break;
+
+ default:
+ LOGMASKED(LOG_TIMER1 | LOG_UNKNOWN, "%s: timer1_tick: Unknown waveform generation mode: %02x\n", machine().describe_context(), WGM1);
+ break;
}
- m_timer1_count += increment;
+ timer1_count += increment;
+ m_timer_prescale_count[1] -= m_timer_prescale[1];
+
+ m_r[TCNT1H] = timer1_count >> 8;
+ m_r[TCNT1L] = (uint8_t)timer1_count;
}
-void avr8_device::update_timer_waveform_gen_mode(uint8_t t, uint8_t mode)
+template <int NumTimers>
+void avr8_device<NumTimers>::update_timer_waveform_gen_mode(uint8_t t, uint8_t mode)
{
int32_t oc_val = -1, ic_val = -1;
-
switch (t)
{
case 0:
- oc_val = AVR8_OCR0A;
+ oc_val = m_r[OCR0A];
ic_val = -1;
break;
case 1:
- oc_val = AVR8_OCR1A;
- ic_val = AVR8_ICR1;
+ oc_val = OCR1A;
+ ic_val = ICR1;
break;
case 2:
- oc_val = AVR8_OCR2A;
+ oc_val = OCR2A;
ic_val = -1;
break;
case 3:
- oc_val = AVR8_OCR3A;
- ic_val = AVR8_ICR3;
+ oc_val = OCR3A;
+ ic_val = ICR3;
break;
case 4:
- oc_val = AVR8_OCR4A;
- ic_val = AVR8_ICR4;
+ oc_val = OCR4A;
+ ic_val = ICR4;
break;
case 5:
- oc_val = AVR8_OCR5A;
- ic_val = AVR8_ICR5;
+ oc_val = OCR5A;
+ ic_val = ICR5;
break;
}
@@ -1683,79 +1958,30 @@ void avr8_device::update_timer_waveform_gen_mode(uint8_t t, uint8_t mode)
break;
}
- if (t == 1)
- {
- m_wgm1 = ((m_r[AVR8_REGIDX_TCCR1B] & AVR8_TCCR1B_WGM1_32_MASK) >> 1) | (m_r[AVR8_REGIDX_TCCR1A] & AVR8_TCCR1A_WGM1_10_MASK);
- }
if (m_timer_top[t] == -1)
{
m_timer_top[t] = 0;
- LOGMASKED((LOG_TIMER0 + t), "%s: update_timer_waveform_gen_mode: Timer %d - Unsupported waveform generation type: %d\n", machine().describe_context(), t, mode);
+ LOGMASKED((LOG_TIMER0 << t), "%s: update_timer_waveform_gen_mode: Timer %d - Unsupported waveform generation type: %d\n", machine().describe_context(), t, mode);
}
}
-void avr8_device::changed_tccr1a(uint8_t data)
-{
- uint8_t oldtccr = AVR8_TCCR1A;
- uint8_t newtccr = data;
- uint8_t changed = newtccr ^ oldtccr;
-
- m_r[AVR8_REGIDX_TCCR1A] = newtccr;
-
- if (changed & AVR8_TCCR1A_WGM1_10_MASK)
- {
- update_timer_waveform_gen_mode(1, AVR8_WGM1);
- }
-
- m_timer1_compare_mode[AVR8_REG_A] = (m_r[AVR8_REGIDX_TCCR1A] & AVR8_TCCR1A_COM1A_MASK) >> AVR8_TCCR1A_COM1A_SHIFT;
- m_timer1_compare_mode[AVR8_REG_B] = (m_r[AVR8_REGIDX_TCCR1A] & AVR8_TCCR1A_COM1B_MASK) >> AVR8_TCCR1A_COM1B_SHIFT;
-}
-
-void avr8_device::update_timer1_input_noise_canceler()
+template <int NumTimers>
+void avr8_device<NumTimers>::update_timer1_input_noise_canceler()
{
LOGMASKED(LOG_TIMER1 | LOG_UNKNOWN, "%s: update_timer1_input_noise_canceler: TODO\n", machine().describe_context());
}
-void avr8_device::update_timer1_input_edge_select()
+template <int NumTimers>
+void avr8_device<NumTimers>::update_timer1_input_edge_select()
{
LOGMASKED(LOG_TIMER1 | LOG_UNKNOWN, "%s: update_timer1_input_edge_select: TODO\n", machine().describe_context());
}
-void avr8_device::changed_tccr1b(uint8_t data)
+template <int NumTimers>
+void avr8_device<NumTimers>::update_ocr1(uint16_t newval, uint8_t reg)
{
- LOGMASKED(LOG_TIMER1, "%s: changed_tccr1b: data = 0x%02X\n", machine().describe_context(), data);
-
- uint8_t oldtccr = AVR8_TCCR1B;
- uint8_t newtccr = data;
- uint8_t changed = newtccr ^ oldtccr;
-
- m_r[AVR8_REGIDX_TCCR1B] = newtccr;
-
- if (changed & AVR8_TCCR1B_ICNC1_MASK)
- {
- update_timer1_input_noise_canceler();
- }
-
- if (changed & AVR8_TCCR1B_ICES1_MASK)
- {
- update_timer1_input_edge_select();
- }
-
- if (changed & AVR8_TCCR1B_WGM1_32_MASK)
- {
- update_timer_waveform_gen_mode(1, AVR8_WGM1);
- }
-
- if (changed & AVR8_TCCR1B_CS_MASK)
- {
- update_timer_clock_source(1, AVR8_TIMER1_CLOCK_SELECT);
- }
-}
-
-void avr8_device::update_ocr1(uint16_t newval, uint8_t reg)
-{
- static const int32_t s_high_indices[3] = { AVR8_REGIDX_OCR1AH, AVR8_REGIDX_OCR1BH, AVR8_REGIDX_OCR1CH };
- static const int32_t s_low_indices[3] = { AVR8_REGIDX_OCR1AL, AVR8_REGIDX_OCR1BL, AVR8_REGIDX_OCR1CL };
+ static const int32_t s_high_indices[3] = { OCR1AH, OCR1BH, OCR1CH };
+ static const int32_t s_low_indices[3] = { OCR1AL, OCR1BL, OCR1CL };
m_r[s_high_indices[reg]] = (uint8_t)(newval >> 8);
m_r[s_low_indices[reg]] = (uint8_t)newval;
m_ocr1[reg] = newval;
@@ -1763,142 +1989,98 @@ void avr8_device::update_ocr1(uint16_t newval, uint8_t reg)
// Timer 2 Handling
-void avr8_device::timer2_tick()
+template <int NumTimers>
+void avr8_device<NumTimers>::timer2_tick_default()
{
- uint16_t count = m_r[AVR8_REGIDX_TCNT2];
- int32_t wgm2 = ((m_r[AVR8_REGIDX_TCCR2B] & AVR8_TCCR2B_WGM2_2_MASK) >> 1) |
- (m_r[AVR8_REGIDX_TCCR2A] & AVR8_TCCR2A_WGM2_10_MASK);
+ LOGMASKED(LOG_TIMER2, "%s: WGM02_PWM_PC: Unimplemented timer#2 waveform generation mode %d\n", machine().describe_context(), WGM2);
+ m_r[TCNT2]++;
+ m_timer_prescale_count[2] -= m_timer_prescale[2];
+}
- // Cache things in array form to avoid a compare+branch inside a potentially high-frequency timer
- //uint8_t compare_mode[2] = { (m_r[AVR8_REGIDX_TCCR2A] & AVR8_TCCR2A_COM2A_MASK) >> AVR8_TCCR2A_COM2A_SHIFT,
- //(m_r[AVR8_REGIDX_TCCR2A] & AVR8_TCCR2A_COM2B_MASK) >> AVR8_TCCR2A_COM2B_SHIFT };
- uint8_t ocr2[2] = { m_r[AVR8_REGIDX_OCR2A], m_r[AVR8_REGIDX_OCR2B] };
- uint8_t ocf2[2] = { (1 << AVR8_TIFR2_OCF2A_SHIFT), (1 << AVR8_TIFR2_OCF2B_SHIFT) };
- int32_t increment = m_timer_increment[2];
+template <int NumTimers>
+void avr8_device<NumTimers>::timer2_tick_norm()
+{
+ LOGMASKED(LOG_TIMER2, "%s: timer2_tick_norm; WGM02_NORMAL\n", machine().describe_context());
+ if (m_r[TCNT2] == 0xff)
+ {
+ m_r[TIFR2] |= TIFR2_TOV2_MASK;
+ }
+ m_r[TCNT2]++;
+ update_interrupt(INTIDX_TOV2);
+ m_timer_prescale_count[2] -= m_timer_prescale[2];
+}
- for (int32_t reg = AVR8_REG_A; reg <= AVR8_REG_B; reg++)
+template <int NumTimers>
+void avr8_device<NumTimers>::timer2_tick_fast_pwm()
+{
+ if (m_r[TCNT2] >= m_r[OCR2A])
{
- switch (wgm2)
+ if (m_r[TCNT2] >= 0xff)
{
- case WGM02_NORMAL:
- if (count == 0xff)
- {
- m_r[AVR8_REGIDX_TIFR2] |= AVR8_TIFR2_TOV2_MASK;
- }
- break;
-
- case WGM02_FAST_PWM:
- if (reg == 0)
- {
- if (count >= m_r[AVR8_REGIDX_OCR2A])
- {
- if (count >= 0xff)
- {
- // Turn on
- m_io->write_byte(AVR8_IO_PORTD, m_io->read_byte(AVR8_IO_PORTD) | (1 << 7));
- m_r[AVR8_REGIDX_TCNT2] = 0;
- m_ocr2_not_reached_yet = true;
- }
- else
- {
- if (m_ocr2_not_reached_yet)
- {
- // Turn off
- m_io->write_byte(AVR8_IO_PORTD, m_io->read_byte(AVR8_IO_PORTD) & ~(1 << 7));
- m_ocr2_not_reached_yet = false;
- }
- }
- }
- }
- break;
-
- case WGM02_FAST_PWM_CMP:
- if (count == ocr2[reg])
- {
- if (reg == 0)
- {
- m_r[AVR8_REGIDX_TIFR2] |= AVR8_TIFR2_TOV2_MASK;
- count = 0;
- increment = 0;
- }
-
- m_r[AVR8_REGIDX_TIFR2] |= ocf2[reg];
- }
- else if (count == 0)
+ // Turn on
+ m_r[PORTD] |= 1 << 7;
+ m_gpio_out_cb[GPIOD](m_r[PORTD]);
+ m_r[TCNT2] = 0;
+ m_ocr2_not_reached_yet = true;
+ }
+ else
+ {
+ if (m_ocr2_not_reached_yet)
{
- if (reg == 0)
- {
- m_r[AVR8_REGIDX_TIFR2] &= ~AVR8_TIFR2_TOV2_MASK;
- }
+ // Turn off
+ m_r[PORTD] &= ~(1 << 7);
+ m_gpio_out_cb[GPIOD](m_r[PORTD]);
+ m_ocr2_not_reached_yet = false;
}
- break;
-
- default:
- LOGMASKED(LOG_TIMER2 | LOG_UNKNOWN, "%s: timer2_tick: Unknown waveform generation mode: %02x\n", machine().describe_context(), wgm2);
- break;
}
}
- m_r[AVR8_REGIDX_TCNT2] += increment;
-
- update_interrupt(AVR8_INTIDX_OCF2A);
- update_interrupt(AVR8_INTIDX_OCF2B);
- update_interrupt(AVR8_INTIDX_TOV2);
+ m_r[TCNT2]++;
+ m_timer_prescale_count[2] -= m_timer_prescale[2];
}
-void avr8_device::changed_tccr2a(uint8_t data)
+template <int NumTimers>
+void avr8_device<NumTimers>::timer2_tick_fast_pwm_cmp()
{
- uint8_t oldtccr = AVR8_TCCR2A;
- uint8_t newtccr = data;
- uint8_t changed = newtccr ^ oldtccr;
+ const uint8_t ocf2[2] = { (1 << TIFR2_OCF2A_SHIFT), (1 << TIFR2_OCF2B_SHIFT) };
+ uint16_t count = m_r[TCNT2];
- AVR8_TCCR2A = data;
+ int32_t increment = 1;
- if (changed & AVR8_TCCR2A_WGM2_10_MASK)
+ if (count == m_r[OCR2A])
{
- update_timer_waveform_gen_mode(2, AVR8_WGM2);
+ m_r[TIFR2] |= TIFR2_TOV2_MASK;
+ count = 0;
+ increment = 0;
+ m_r[TIFR2] |= ocf2[AVR8_REG_A];
}
-}
-
-void avr8_device::timer2_force_output_compare(int reg)
-{
- LOGMASKED(LOG_TIMER2 | LOG_UNKNOWN, "%s: force_output_compare: TODO; should be forcing OC2%c\n", machine().describe_context(), avr8_reg_name[reg]);
-}
-
-void avr8_device::changed_tccr2b(uint8_t data)
-{
- LOGMASKED(LOG_TIMER2, "%s: changed_tccr2b: data = 0x%02X\n", machine().describe_context(), data);
-
- uint8_t oldtccr = AVR8_TCCR2B;
- uint8_t newtccr = data;
- uint8_t changed = newtccr ^ oldtccr;
-
- AVR8_TCCR2B = data;
-
- if (changed & AVR8_TCCR2B_FOC2A_MASK)
+ else if (count == 0)
{
- timer2_force_output_compare(AVR8_REG_A);
+ m_r[TIFR2] &= ~TIFR2_TOV2_MASK;
}
- if (changed & AVR8_TCCR2B_FOC2B_MASK)
+ if (count == m_r[OCR2B])
{
- timer2_force_output_compare(AVR8_REG_B);
+ m_r[TIFR2] |= ocf2[AVR8_REG_B];
}
- if (changed & AVR8_TCCR2B_WGM2_2_MASK)
- {
- update_timer_waveform_gen_mode(2, AVR8_WGM2);
- }
+ count += increment;
- if (changed & AVR8_TCCR2B_CS_MASK)
- {
- update_timer_clock_source(2, AVR8_TIMER2_CLOCK_SELECT);
- }
+ update_interrupt(INTIDX_TOV2);
+ m_r[TCNT2] = count;
+ m_timer_prescale_count[2] -= m_timer_prescale[2];
+}
+
+template <int NumTimers>
+void avr8_device<NumTimers>::timer2_force_output_compare(int reg)
+{
+ LOGMASKED(LOG_TIMER2 | LOG_UNKNOWN, "%s: force_output_compare: TODO; should be forcing OC2%c\n", machine().describe_context(), 'A' + reg);
}
-void avr8_device::update_ocr2(uint8_t newval, uint8_t reg)
+template <int NumTimers>
+void avr8_device<NumTimers>::update_ocr2(uint8_t newval, uint8_t reg)
{
- m_r[(reg == AVR8_REG_A) ? AVR8_REGIDX_OCR2A : AVR8_REGIDX_OCR2B] = newval;
+ m_r[(reg == AVR8_REG_A) ? OCR2A : OCR2B] = newval;
// Nothing needs to be done? All handled in timer callback
}
@@ -1906,35 +2088,29 @@ void avr8_device::update_ocr2(uint8_t newval, uint8_t reg)
/************************************************************************************************/
// Timer 3 Handling
-void avr8_device::timer3_tick()
+template <int NumTimers>
+void avr8_device<NumTimers>::timer3_tick()
{
}
/************************************************************************************************/
-void avr8_device::timer4_tick()
+template <int NumTimers>
+void avr8_device<NumTimers>::timer4_tick()
{
/* TODO: Handle comparison, setting OC1x pins, detection of BOTTOM and TOP */
- LOGMASKED(LOG_TIMER4_TICK, "%s: AVR8_WGM4: %d\n", machine().describe_context(), AVR8_WGM4);
- LOGMASKED(LOG_TIMER4_TICK, "%s: AVR8_TCCR4A_COM4B: %d\n", machine().describe_context(), AVR8_TCCR4A_COM4B);
+ LOGMASKED(LOG_TIMER4_TICK, "%s: WGM4: %d\n", machine().describe_context(), WGM4);
+ LOGMASKED(LOG_TIMER4_TICK, "%s: TCCR4A_COM4B: %d\n", machine().describe_context(), TCCR4A_COM4B);
- uint16_t count = (m_r[AVR8_REGIDX_TCNT4H] << 8) | m_r[AVR8_REGIDX_TCNT4L];
+ uint16_t count = (m_r[TCNT4H] << 8) | m_r[TCNT4L];
+ int32_t increment = 1;
- // Cache things in array form to avoid a compare+branch inside a potentially high-frequency timer
- // uint8_t compare_mode[2] = { (m_r[AVR8_REGIDX_TCCR1A] & AVR8_TCCR1A_COM1A_MASK) >> AVR8_TCCR1A_COM1A_SHIFT,
- // (m_r[AVR8_REGIDX_TCCR1A] & AVR8_TCCR1A_COM1B_MASK) >> AVR8_TCCR1A_COM1B_SHIFT };
- // uint16_t ocr4[2] = { static_cast<uint16_t>((m_r[AVR8_REGIDX_OCR4AH] << 8) | m_r[AVR8_REGIDX_OCR4AL]),
- // static_cast<uint16_t>((m_r[AVR8_REGIDX_OCR4BH] << 8) | m_r[AVR8_REGIDX_OCR4BL]) };
- // TODO uint8_t ocf4[2] = { (1 << AVR8_TIFR4_OCF4A_SHIFT), (1 << AVR8_TIFR4_OCF4B_SHIFT) };
- // TODO uint8_t int4[2] = { AVR8_INTIDX_OCF4A, AVR8_INTIDX_OCF4B };
- int32_t increment = m_timer_increment[4];
-
- switch (AVR8_WGM4)
+ switch (WGM4)
{
case WGM4_FAST_PWM_8:
case WGM4_FAST_PWM_9:
case WGM4_FAST_PWM_10:
- switch (AVR8_TCCR4A_COM4B)
+ switch (TCCR4A_COM4B)
{
case 0: /* Normal Operation */
break;
@@ -1945,13 +2121,15 @@ void avr8_device::timer4_tick()
{
// Clear OC0B
LOGMASKED(LOG_TIMER4, "%s: timer4: non-inverting mode, Clear OC0B\n", machine().describe_context());
- m_io->write_byte(AVR8_IO_PORTG, m_io->read_byte(AVR8_IO_PORTG) & ~(1 << 5));
+ m_r[PORTG] &= ~(1 << 5);
+ m_gpio_out_cb[GPIOG](m_r[PORTG]);
}
else if (count == 0)
{
// Set OC0B
LOGMASKED(LOG_TIMER4, "%s: timer4: non-inverting mode, Set OC0B\n", machine().describe_context());
- m_io->write_byte(AVR8_IO_PORTG, m_io->read_byte(AVR8_IO_PORTG) | (1 << 5));
+ m_r[PORTG] |= 1 << 5;
+ m_gpio_out_cb[GPIOG](m_r[PORTG]);
}
break;
case 3: /* Inverting mode */
@@ -1959,13 +2137,15 @@ void avr8_device::timer4_tick()
{
// Set OC0B
LOGMASKED(LOG_TIMER4, "%s: timer4: inverting mode, Clear OC0B\n", machine().describe_context());
- m_io->write_byte(AVR8_IO_PORTG, m_io->read_byte(AVR8_IO_PORTG) | (1 << 5));
+ m_r[PORTG] |= 1 << 5;
+ m_gpio_out_cb[GPIOG](m_r[PORTG]);
}
else if (count == 0)
{
// Clear OC0B
LOGMASKED(LOG_TIMER4, "%s: timer4: inverting mode, Set OC0B\n", machine().describe_context());
- m_io->write_byte(AVR8_IO_PORTG, m_io->read_byte(AVR8_IO_PORTG) & ~(1 << 5));
+ m_r[PORTG] &= ~(1 << 5);
+ m_gpio_out_cb[GPIOG](m_r[PORTG]);
}
break;
}
@@ -1975,8 +2155,8 @@ void avr8_device::timer4_tick()
LOGMASKED(LOG_TIMER4, "%s: timer4: tick WGM4_CTC_OCR: %d\n", machine().describe_context(), count);
if (count == 0xffff)
{
- m_r[AVR8_REGIDX_TIFR4] |= AVR8_TIFR4_TOV4_MASK;
- update_interrupt(AVR8_INTIDX_TOV4);
+ m_r[TIFR4] |= TIFR4_TOV4_MASK;
+ update_interrupt(INTIDX_TOV4);
count = 0;
increment = 0;
}
@@ -1989,127 +2169,56 @@ void avr8_device::timer4_tick()
break;
default:
- LOGMASKED(LOG_TIMER4 | LOG_UNKNOWN, "%s: timer4_tick: Unknown waveform generation mode: %02x\n", machine().describe_context(), AVR8_WGM4);
+ LOGMASKED(LOG_TIMER4 | LOG_UNKNOWN, "%s: timer4_tick: Unknown waveform generation mode: %02x\n", machine().describe_context(), WGM4);
break;
}
count += increment;
- m_r[AVR8_REGIDX_TCNT4H] = (count >> 8) & 0xff;
- m_r[AVR8_REGIDX_TCNT4L] = count & 0xff;
+ m_r[TCNT4H] = (count >> 8) & 0xff;
+ m_r[TCNT4L] = count & 0xff;
}
-void avr8_device::update_timer_clock_source(uint8_t t, uint8_t clock_select)
+template <int NumTimers>
+template <int Timer>
+void avr8_device<NumTimers>::update_timer_clock_source(uint8_t clock_select, const uint8_t old_clock_select)
{
- static const int s_prescale_values[2][8] =
+ static const int32_t s_prescale_values[2][8] =
{
- { 0, 1, 8, 64, 256, 1024, -1, -1 }, // T0/T1/T3/T4/T5
- { 0, 1, 8, 32, 64, 128, 256, 1024 } // T2
+ { 0x0000ffff, 1, 8, 64, 256, 1024, -1, -1 }, // T0/T1/T3/T4/T5
+ { 0x0000ffff, 1, 8, 32, 64, 128, 256, 1024 } // T2
};
- m_timer_prescale[t] = s_prescale_values[(t == 2) ? 1 : 0][clock_select];
+ const int32_t prescale_divisor = s_prescale_values[(Timer == 2) ? 1 : 0][clock_select];
+ const uint16_t old_prescale = s_prescale_values[(Timer == 2) ? 1 : 0][old_clock_select];
+ m_timer_prescale[Timer] = (uint16_t)prescale_divisor;
- LOGMASKED((LOG_TIMER0 + t), "%s: update_timer_clock_source: t = %d, cs = %d\n", machine().describe_context(), t, clock_select);
+ LOGMASKED(LOG_TIMER0 << Timer, "%s: update_timer_clock_source: t = %d, cs = %d\n", machine().describe_context(), Timer, clock_select);
- if (m_timer_prescale[t] == 0xffff)
+ if (prescale_divisor == -1)
{
- LOGMASKED((LOG_TIMER0 + t), "%s: timer%d: update_timer_clock_source: External trigger mode not implemented yet\n", machine().describe_context(), t);
- m_timer_prescale[t] = 0;
+ LOGMASKED(LOG_TIMER0 << Timer, "%s: timer%d: update_timer_clock_source: External trigger mode not implemented yet\n", machine().describe_context(), Timer);
+ m_timer_prescale[Timer] = 0xffff;
}
- if (m_timer_prescale_count[t] > m_timer_prescale[t])
+ if (old_prescale == 0xffff || m_timer_prescale_count[Timer] > m_timer_prescale[Timer])
{
- m_timer_prescale_count[t] = m_timer_prescale[t] - 1;
+ m_timer_prescale_count[Timer] = m_timer_prescale[Timer];
}
}
-void avr8_device::changed_tccr3a(uint8_t data)
-{
- // TODO
- // AVR8_TCCR3A = data;
-}
-
-void avr8_device::changed_tccr3b(uint8_t data)
-{
- LOGMASKED(LOG_TIMER3 | LOG_UNKNOWN, "%s: (not yet implemented) changed_tccr3b: data = %02X\n", machine().describe_context(), data);
-}
-
-void avr8_device::changed_tccr3c(uint8_t data)
-{
- // uint8_t oldtccr = AVR8_TCCR3C;
- // uint8_t newtccr = data;
- // uint8_t changed = newtccr ^ oldtccr;
- LOGMASKED(LOG_TIMER3 | LOG_UNKNOWN, "%s: (not yet implemented) changed_tccr3c: data = %02X\n", machine().describe_context(), data);
-
- // AVR8_TCCR3C = data;
-}
-
-void avr8_device::changed_tccr4a(uint8_t data)
-{
- uint8_t oldtccr = AVR8_TCCR4A;
- uint8_t newtccr = data;
- uint8_t changed = newtccr ^ oldtccr;
-
- AVR8_TCCR4A = data;
-
- if (changed & AVR8_TCCR4A_WGM4_10_MASK)
- {
- update_timer_waveform_gen_mode(4, AVR8_WGM4);
- }
-}
-
-void avr8_device::changed_tccr4b(uint8_t data)
-{
- LOGMASKED(LOG_TIMER4, "%s: changed_tccr4b: data = %02X\n", machine().describe_context(), data);
-
- uint8_t oldtccr = AVR8_TCCR4B;
- uint8_t newtccr = data;
- uint8_t changed = newtccr ^ oldtccr;
-
- AVR8_TCCR4B = data;
-
- if (changed & AVR8_TCCR4B_FOC4A_MASK)
- {
- // TODO
- // timer4_force_output_compare(AVR8_REG_A);
- }
-
- if (changed & AVR8_TCCR4B_FOC4B_MASK)
- {
- // TODO
- // timer4_force_output_compare(AVR8_REG_B);
- }
-
- if (changed & AVR8_TCCR4B_WGM4_32_MASK)
- {
- update_timer_waveform_gen_mode(4, AVR8_WGM4);
- }
-
- if (changed & AVR8_TCCR4B_CS_MASK)
- {
- update_timer_clock_source(4, AVR8_TIMER4_CLOCK_SELECT);
- }
-}
-
-void avr8_device::changed_tccr4c(uint8_t data)
-{
- // uint8_t oldtccr = AVR8_TCCR4C;
- // uint8_t newtccr = data;
- // uint8_t changed = newtccr ^ oldtccr;
-
- AVR8_TCCR4C = data;
-}
-
/************************************************************************************************/
// Timer 5 Handling
-void avr8_device::timer5_tick()
+
+template <int NumTimers>
+void avr8_device<NumTimers>::timer5_tick()
{
- LOGMASKED(LOG_TIMER5_TICK, "%s: AVR8_WGM5: %d\n", machine().describe_context(), AVR8_WGM5);
- LOGMASKED(LOG_TIMER5_TICK, "%s: AVR8_TCCR5A_COM5B: %d\n", machine().describe_context(), AVR8_TCCR5A_COM5B);
+ LOGMASKED(LOG_TIMER5_TICK, "%s: WGM5: %d\n", machine().describe_context(), WGM5);
+ LOGMASKED(LOG_TIMER5_TICK, "%s: TCCR5A_COM5B: %d\n", machine().describe_context(), TCCR5A_COM5B);
- uint16_t count = (AVR8_TCNT5H << 8) + AVR8_TCNT5L;
- int32_t increment = m_timer_increment[5];
+ uint16_t count = (m_r[TCNT5H] << 8) + m_r[TCNT5L];
+ int32_t increment = 1;
- switch (AVR8_WGM5)
+ switch (WGM5)
{
case WGM5_NORMAL:
case WGM5_PWM_8_PC:
@@ -2126,12 +2235,12 @@ void avr8_device::timer5_tick()
case WGM5_CTC_ICR:
case WGM5_FAST_PWM_ICR:
case WGM5_FAST_PWM_OCR:
- LOGMASKED(LOG_TIMER5 | LOG_UNKNOWN, "%s: Unimplemented timer5 waveform generation mode: AVR8_WGM5 = 0x%02X\n", machine().describe_context(), AVR8_WGM5);
+ LOGMASKED(LOG_TIMER5 | LOG_UNKNOWN, "%s: Unimplemented timer5 waveform generation mode: WGM5 = 0x%02X\n", machine().describe_context(), WGM5);
break;
case WGM5_CTC_OCR:
// TODO: Please verify, might be wrong
- switch (AVR8_TCCR5A_COM5B)
+ switch (TCCR5A_COM5B)
{
case 0: /* Normal Operation */
if (count == m_timer_top[5])
@@ -2144,7 +2253,8 @@ void avr8_device::timer5_tick()
{
m_timer_top[5] = 0;
LOGMASKED(LOG_TIMER5, "%s: timer5: Toggle OC5B on compare match\n", machine().describe_context());
- m_io->write_byte(AVR8_IO_PORTL, m_io->read_byte(AVR8_IO_PORTL) ^ (1 << 4));
+ m_r[PORTL] ^= 1 << 4;
+ m_gpio_out_cb[GPIOL](m_r[PORTL]);
}
break;
case 2: /* Clear OC5B on compare match */
@@ -2153,7 +2263,8 @@ void avr8_device::timer5_tick()
m_timer_top[5] = 0;
// Clear OC5B
LOGMASKED(LOG_TIMER5, "%s: timer5: Clear OC5B on compare match\n", machine().describe_context());
- m_io->write_byte(AVR8_IO_PORTL, m_io->read_byte(AVR8_IO_PORTL) & ~(1 << 4));
+ m_r[PORTL] &= ~(1 << 4);
+ m_gpio_out_cb[GPIOL](m_r[PORTL]);
}
break;
case 3: /* Set OC5B on compare match */
@@ -2161,173 +2272,186 @@ void avr8_device::timer5_tick()
{
m_timer_top[5] = 0;
LOGMASKED(LOG_TIMER5, "%s: timer5: Set OC5B on compare match\n", machine().describe_context());
- m_io->write_byte(AVR8_IO_PORTL, m_io->read_byte(AVR8_IO_PORTL) | (1 << 4));
+ m_r[PORTL] |= 1 << 4;
+ m_gpio_out_cb[GPIOL](m_r[PORTL]);
}
break;
}
break;
default:
- LOGMASKED(LOG_TIMER5 | LOG_UNKNOWN, "%s: timer5: Unknown waveform generation mode: %02x\n", machine().describe_context(), AVR8_WGM5);
+ LOGMASKED(LOG_TIMER5 | LOG_UNKNOWN, "%s: timer5: Unknown waveform generation mode: %02x\n", machine().describe_context(), WGM5);
break;
}
count += increment;
- m_r[AVR8_REGIDX_TCNT5H] = (count >> 8) & 0xff;
- m_r[AVR8_REGIDX_TCNT5L] = count & 0xff;
+ m_r[TCNT5H] = (count >> 8) & 0xff;
+ m_r[TCNT5L] = count & 0xff;
}
-void avr8_device::changed_tccr5a(uint8_t data)
-{
- uint8_t oldtccr = AVR8_TCCR5A;
- uint8_t newtccr = data;
- uint8_t changed = newtccr ^ oldtccr;
+/************************************************************************************************/
- AVR8_TCCR5A = data;
- if (changed & AVR8_TCCR5A_WGM5_10_MASK)
- {
- update_timer_waveform_gen_mode(5, AVR8_WGM5);
- }
-}
+/****************/
+/* ADC Handling */
+/****************/
-void avr8_device::changed_tccr5b(uint8_t data)
+template <int NumTimers>
+void avr8_device<NumTimers>::adc_start_conversion()
{
- LOGMASKED(LOG_TIMER5, "%s: changed_tccr5b: data = %02X\n", machine().describe_context(), data);
-
- uint8_t oldtccr = AVR8_TCCR5B;
- uint8_t newtccr = data;
- uint8_t changed = newtccr ^ oldtccr;
+ // set capture in progress flag
+ m_r[ADCSRA] |= ADCSRA_ADSC_MASK;
- AVR8_TCCR5B = data;
-
- if (changed & AVR8_TCCR5C_FOC5A_MASK)
+ // get a sample - the sample-and-hold circuit will hold this for the duration of the conversion
+ if (ADMUX_MUX < 0x8)
{
- // TODO
- // timer5_force_output_compare(AVR8_REG_A);
+ m_adc_sample = m_adc_in_cb[ADMUX_MUX]() & 0x3ff;
}
-
- if (changed & AVR8_TCCR5C_FOC5B_MASK)
+ else if (ADMUX_MUX == 0xe)
{
- // TODO
- // timer5_force_output_compare(AVR8_REG_B);
+ // 1.1V (Vbg)
+ // FIXME: the value this acquires depends on what the reference source is set to
+ logerror("%s: Using unimplemented 1.1V reference voltage as ADC input\n", machine().describe_context());
+ m_adc_sample = 0x3ff;
}
-
- if (changed & AVR8_TCCR5C_FOC5C_MASK)
+ else if (ADMUX_MUX == 0x0f)
{
- // TODO
- // timer5_force_output_compare(AVR8_REG_C);
+ // 0V (GND)
+ m_adc_sample = 0;
}
-
- if (changed & AVR8_TCCR5B_WGM5_32_MASK)
+ else
{
- update_timer_waveform_gen_mode(5, AVR8_WGM5);
+ logerror("%s: Using reserved ADC input 0x%X\n", machine().describe_context(), ADMUX_MUX);
+ m_adc_sample = 0;
}
- if (changed & AVR8_TCCR5B_CS_MASK)
- {
- update_timer_clock_source(5, AVR8_TIMER5_CLOCK_SELECT);
- }
+ // wait for conversion to complete
+ int const scale = 1 << std::max(ADCSRA_ADPS, 1);
+ m_adc_timer->adjust(attotime::from_ticks((m_adc_first ? 25 : 13) * scale, clock()));
}
-/************************************************************************************************/
+template <int NumTimers>
+TIMER_CALLBACK_MEMBER(avr8_device<NumTimers>::adc_conversion_complete)
+{
+ // set conversion result
+ m_adc_result = m_adc_sample;
+ if (!m_adc_hold)
+ m_adc_data = m_adc_result;
+ // clear conversion in progress flag, set conversion interrupt flag
+ m_r[ADCSRA] &= ~ADCSRA_ADSC_MASK;
+ m_r[ADCSRA] |= ADCSRA_ADIF_MASK;
+
+ // trigger another conversion if appropriate
+ if (ADCSRA_ADATE && (ADCSRB_ADTS == 0))
+ adc_start_conversion();
+}
+
+/************************************************************************************************/
/****************/
/* SPI Handling */
/****************/
-void avr8_device::enable_spi()
+template <int NumTimers>
+void avr8_device<NumTimers>::enable_spi()
{
// TODO
}
-void avr8_device::disable_spi()
+template <int NumTimers>
+void avr8_device<NumTimers>::disable_spi()
{
// TODO
}
-void avr8_device::spi_update_masterslave_select()
+template <int NumTimers>
+void avr8_device<NumTimers>::spi_update_masterslave_select()
{
// TODO
}
-void avr8_device::spi_update_clock_polarity()
+template <int NumTimers>
+void avr8_device<NumTimers>::spi_update_clock_polarity()
{
// TODO
}
-void avr8_device::spi_update_clock_phase()
+template <int NumTimers>
+void avr8_device<NumTimers>::spi_update_clock_phase()
{
// TODO
}
-void avr8_device::spi_update_clock_rate()
+template <int NumTimers>
+void avr8_device<NumTimers>::spi_update_clock_rate()
{
static const uint8_t s_spi_clock_divisor[8] =
{
4, 16, 64, 128, 2, 8, 32, 64
};
- m_spi_prescale = s_spi_clock_divisor[AVR8_SPI_RATE];
+ m_spi_prescale = s_spi_clock_divisor[SPI_RATE];
m_spi_prescale_count &= m_spi_prescale - 1;
}
-void avr8_device::change_spcr(uint8_t data)
+template <int NumTimers>
+void avr8_device<NumTimers>::change_spcr(uint8_t data)
{
- uint8_t oldspcr = AVR8_SPCR;
+ uint8_t oldspcr = m_r[SPCR];
uint8_t newspcr = data;
uint8_t changed = newspcr ^ oldspcr;
uint8_t high_to_low = ~newspcr & oldspcr;
uint8_t low_to_high = newspcr & ~oldspcr;
- AVR8_SPCR = data;
+ m_r[SPCR] = data;
- if (changed & AVR8_SPCR_SPIE_MASK)
+ if (changed & SPCR_SPIE_MASK)
{
// Check for SPI interrupt condition
- update_interrupt(AVR8_INTIDX_SPI);
+ update_interrupt(INTIDX_SPI);
}
- if (low_to_high & AVR8_SPCR_SPE_MASK)
+ if (low_to_high & SPCR_SPE_MASK)
{
enable_spi();
}
- else if (high_to_low & AVR8_SPCR_SPE_MASK)
+ else if (high_to_low & SPCR_SPE_MASK)
{
disable_spi();
}
- if (changed & AVR8_SPCR_MSTR_MASK)
+ if (changed & SPCR_MSTR_MASK)
{
spi_update_masterslave_select();
}
- if (changed & AVR8_SPCR_CPOL_MASK)
+ if (changed & SPCR_CPOL_MASK)
{
spi_update_clock_polarity();
}
- if (changed & AVR8_SPCR_CPHA_MASK)
+ if (changed & SPCR_CPHA_MASK)
{
spi_update_clock_phase();
}
- if (changed & AVR8_SPCR_SPR_MASK)
+ if (changed & SPCR_SPR_MASK)
{
spi_update_clock_rate();
}
}
-void avr8_device::change_spsr(uint8_t data)
+template <int NumTimers>
+void avr8_device<NumTimers>::change_spsr(uint8_t data)
{
- uint8_t oldspsr = AVR8_SPSR;
+ uint8_t oldspsr = m_r[SPSR];
uint8_t newspsr = data;
uint8_t changed = newspsr ^ oldspsr;
- AVR8_SPSR &= ~1;
- AVR8_SPSR |= data & 1;
+ m_r[SPSR] &= ~1;
+ m_r[SPSR] |= data & 1;
- if (changed & AVR8_SPSR_SPR2X_MASK)
+ if (changed & SPSR_SPR2X_MASK)
{
spi_update_clock_rate();
}
@@ -2335,848 +2459,989 @@ void avr8_device::change_spsr(uint8_t data)
/*****************************************************************************/
-void avr8_device::regs_w(offs_t offset, uint8_t data)
-{
- switch (offset)
- {
- case AVR8_REGIDX_R0:
- case AVR8_REGIDX_R1:
- case AVR8_REGIDX_R2:
- case AVR8_REGIDX_R3:
- case AVR8_REGIDX_R4:
- case AVR8_REGIDX_R5:
- case AVR8_REGIDX_R6:
- case AVR8_REGIDX_R7:
- case AVR8_REGIDX_R8:
- case AVR8_REGIDX_R9:
- case AVR8_REGIDX_R10:
- case AVR8_REGIDX_R11:
- case AVR8_REGIDX_R12:
- case AVR8_REGIDX_R13:
- case AVR8_REGIDX_R14:
- case AVR8_REGIDX_R15:
- case AVR8_REGIDX_R16:
- case AVR8_REGIDX_R17:
- case AVR8_REGIDX_R18:
- case AVR8_REGIDX_R19:
- case AVR8_REGIDX_R20:
- case AVR8_REGIDX_R21:
- case AVR8_REGIDX_R22:
- case AVR8_REGIDX_R23:
- case AVR8_REGIDX_R24:
- case AVR8_REGIDX_R25:
- case AVR8_REGIDX_R26:
- case AVR8_REGIDX_R27:
- case AVR8_REGIDX_R28:
- case AVR8_REGIDX_R29:
- case AVR8_REGIDX_R30:
- case AVR8_REGIDX_R31:
- m_r[offset] = data;
- break;
+template <int NumTimers>
+template <int Port>
+uint8_t avr8_device<NumTimers>::gpio_r()
+{
+ static constexpr uint16_t PORT_TO_REG[11] =
+ {
+ PORTA,
+ PORTB,
+ PORTC,
+ PORTD,
+ PORTE,
+ PORTF,
+ PORTG,
+ PORTH,
+ PORTJ,
+ PORTK,
+ PORTL
+ };
+ static constexpr char PORT_CHARS[GPIO_COUNT] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L' };
+ LOGMASKED(LOG_GPIO, "%s: Huh%c(%d) Read: %02x\n", machine().describe_context(), PORT_CHARS[Port], Port, m_r[PORT_TO_REG[Port]]);
+ return m_r[PORT_TO_REG[Port]];
+}
+
+template <int NumTimers>
+template <int Port>
+uint8_t avr8_device<NumTimers>::pin_r()
+{
+ static constexpr char PORT_CHARS[GPIO_COUNT] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L' };
+ // TODO: account for DDRH
+ const uint8_t data = m_gpio_in_cb[Port]();
+ LOGMASKED(LOG_GPIO, "%s: PIN%c(%d) Read: %02x\n", machine().describe_context(), PORT_CHARS[Port], Port, data);
+ return data;
+}
+
+template <int NumTimers>
+template <int Port>
+void avr8_device<NumTimers>::port_w(uint8_t data)
+{
+ static constexpr char PORT_CHARS[GPIO_COUNT] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L' };
+ static constexpr uint16_t PORT_TO_REG[11] =
+ {
+ PORTA,
+ PORTB,
+ PORTC,
+ PORTD,
+ PORTE,
+ PORTF,
+ PORTG,
+ PORTH,
+ PORTJ,
+ PORTK,
+ PORTL
+ };
- case AVR8_REGIDX_PORTA:
- LOGMASKED(LOG_GPIO, "%s: PORTA Write: %02x\n", machine().describe_context(), data);
- m_io->write_byte(AVR8_IO_PORTA, data);
- m_r[AVR8_REGIDX_PORTA] = data;
- break;
+ LOGMASKED(LOG_GPIO, "%s: PORT%c Write: %02x\n", machine().describe_context(), PORT_CHARS[Port], data);
+ m_r[PORT_TO_REG[Port]] = data;
+ LOGMASKED(LOG_GPIO, "%s: PORT%c Write, XYZ m_r[%d[%d]] = %02x\n", machine().describe_context(), PORT_CHARS[Port], PORT_TO_REG[Port], Port, data);
+ m_gpio_out_cb[Port](data);
+}
- case AVR8_REGIDX_PORTB:
- LOGMASKED(LOG_GPIO, "%s: PORTB Write: %02x\n", machine().describe_context(), data);
- m_io->write_byte(AVR8_IO_PORTB, data);
- m_r[AVR8_REGIDX_PORTB] = data;
- break;
+template <int NumTimers>
+void avr8_device<NumTimers>::tccr0a_w(uint8_t data)
+{
+ LOGMASKED(LOG_TIMER0, "%s: TCCR0A = %02x\n", machine().describe_context(), data);
+ const uint8_t oldtccr = m_r[TCCR0A];
+ const uint8_t newtccr = data;
+ const uint8_t changed = newtccr ^ oldtccr;
+ m_r[TCCR0A] = data;
- case AVR8_REGIDX_PORTC:
- LOGMASKED(LOG_GPIO, "%s: PORTC Write: %02x\n", machine().describe_context(), data);
- m_io->write_byte(AVR8_IO_PORTC, data);
- m_r[AVR8_REGIDX_PORTC] = data;
- break;
+ if (changed & TCCR0A_WGM0_10_MASK)
+ {
+ update_timer_waveform_gen_mode(0, WGM0);
+ }
- case AVR8_REGIDX_PORTD:
- LOGMASKED(LOG_GPIO, "%s: PORTD Write: %02x\n", machine().describe_context(), data);
- m_io->write_byte(AVR8_IO_PORTD, data);
- m_r[AVR8_REGIDX_PORTD] = data;
- break;
+ m_timer0_tick = m_timer0_ticks[(WGM0 << 2) | TCCR0A_COM0B];
+}
- case AVR8_REGIDX_PORTE:
- LOGMASKED(LOG_GPIO, "%s: PORTE Write: %02x\n", machine().describe_context(), data);
- m_io->write_byte(AVR8_IO_PORTE, data);
- m_r[AVR8_REGIDX_PORTE] = data;
- break;
+template <int NumTimers>
+void avr8_device<NumTimers>::tccr0b_w(uint8_t data)
+{
+ LOGMASKED(LOG_TIMER0, "%s: TCCR0B = %02x\n", machine().describe_context(), data);
+ const uint8_t oldtccr = m_r[TCCR0B];
+ const uint8_t newtccr = data;
+ const uint8_t changed = newtccr ^ oldtccr;
+ const uint8_t oldcs = m_r[TCCR0B] & TCCR0B_CS_MASK;
- case AVR8_REGIDX_PORTF:
- LOGMASKED(LOG_GPIO, "%s: PORTF Write: %02x\n", machine().describe_context(), data);
- m_io->write_byte(AVR8_IO_PORTF, data);
- m_r[AVR8_REGIDX_PORTF] = data;
- break;
+ m_r[TCCR0B] = data;
- case AVR8_REGIDX_PORTG:
- LOGMASKED(LOG_GPIO, "%s: PORTG Write: %02x\n", machine().describe_context(), data);
- m_io->write_byte(AVR8_IO_PORTG, data);
- m_r[AVR8_REGIDX_PORTG] = data;
- break;
+ if (changed & TCCR0B_FOC0A_MASK)
+ {
+ // TODO
+ timer0_force_output_compare(AVR8_REG_A);
+ }
- case AVR8_REGIDX_PORTH:
- LOGMASKED(LOG_GPIO, "%s: PORTH Write: %02x\n", machine().describe_context(), data);
- m_io->write_byte(AVR8_IO_PORTH, data);
- m_r[AVR8_REGIDX_PORTH] = data;
- break;
+ if (changed & TCCR0B_FOC0B_MASK)
+ {
+ // TODO
+ timer0_force_output_compare(AVR8_REG_B);
+ }
- case AVR8_REGIDX_PORTJ:
- LOGMASKED(LOG_GPIO, "%s: PORTJ Write: %02x\n", machine().describe_context(), data);
- m_io->write_byte(AVR8_IO_PORTJ, data);
- m_r[AVR8_REGIDX_PORTJ] = data;
- break;
+ if (changed & TCCR0B_WGM0_2_MASK)
+ {
+ update_timer_waveform_gen_mode(0, WGM0);
+ }
- case AVR8_REGIDX_PORTK:
- LOGMASKED(LOG_GPIO, "%s: PORTK Write: %02x\n", machine().describe_context(), data);
- m_io->write_byte(AVR8_IO_PORTK, data);
- m_r[AVR8_REGIDX_PORTK] = data;
- break;
+ if (changed & TCCR0B_CS_MASK)
+ {
+ update_timer_clock_source<0>(TIMER0_CLOCK_SELECT, oldcs);
+ }
- case AVR8_REGIDX_PORTL:
- LOGMASKED(LOG_GPIO, "%s: PORTL Write: %02x\n", machine().describe_context(), data);
- m_io->write_byte(AVR8_IO_PORTL, data);
- m_r[AVR8_REGIDX_PORTL] = data;
- break;
+ m_timer0_tick = m_timer0_ticks[(WGM0 << 2) | TCCR0A_COM0B];
+}
- case AVR8_REGIDX_DDRA:
- case AVR8_REGIDX_DDRB:
- case AVR8_REGIDX_DDRC:
- case AVR8_REGIDX_DDRD:
- case AVR8_REGIDX_SREG:
- case AVR8_REGIDX_RAMPZ:
- case AVR8_REGIDX_SPH:
- case AVR8_REGIDX_SPL:
- m_r[offset] = data;
- break;
+template <int NumTimers>
+void avr8_device<NumTimers>::ocr0a_w(uint8_t data)
+{
+ LOGMASKED(LOG_TIMER0, "%s: OCR0A = %02x\n", machine().describe_context(), data);
+ update_ocr0(data, AVR8_REG_A);
+}
- case AVR8_REGIDX_TCCR0B:
- LOGMASKED(LOG_TIMER0, "%s: TCCR0B = %02x\n", machine().describe_context(), data);
- changed_tccr0b(data);
- break;
+template <int NumTimers>
+void avr8_device<NumTimers>::ocr0b_w(uint8_t data)
+{
+ LOGMASKED(LOG_TIMER0, "%s: OCR0B = %02x\n", machine().describe_context(), data);
+ update_ocr0(data, AVR8_REG_B);
+}
- case AVR8_REGIDX_TCCR0A:
- LOGMASKED(LOG_TIMER0, "%s: TCCR0A = %02x\n", machine().describe_context(), data);
- changed_tccr0a(data);
- break;
+template <int NumTimers>
+void avr8_device<NumTimers>::tifr0_w(uint8_t data)
+{
+ LOGMASKED(LOG_TIMER0, "%s: TIFR0 = %02x\n", machine().describe_context(), data);
+ m_r[TIFR0] &= ~(data & TIFR0_MASK);
+ update_interrupt(INTIDX_OCF0A);
+ update_interrupt(INTIDX_OCF0B);
+ update_interrupt(INTIDX_TOV0);
+}
- case AVR8_REGIDX_OCR0A:
- LOGMASKED(LOG_TIMER0, "%s: OCR0A = %02x\n", machine().describe_context(), data);
- update_ocr0(data, AVR8_REG_A);
- break;
+template <int NumTimers>
+void avr8_device<NumTimers>::tifr1_w(uint8_t data)
+{
+ LOGMASKED(LOG_TIMER1, "%s: TIFR1 = %02x\n", machine().describe_context(), data);
+ m_r[TIFR1] &= ~(data & TIFR1_MASK);
+ update_interrupt(INTIDX_ICF1);
+ update_interrupt(INTIDX_OCF1A);
+ update_interrupt(INTIDX_OCF1B);
+ update_interrupt(INTIDX_TOV1);
+}
- case AVR8_REGIDX_OCR0B:
- LOGMASKED(LOG_TIMER0, "%s: OCR0B = %02x\n", machine().describe_context(), data);
- update_ocr0(data, AVR8_REG_B);
- break;
+template <int NumTimers>
+void avr8_device<NumTimers>::tifr2_w(uint8_t data)
+{
+ LOGMASKED(LOG_TIMER2, "%s: TIFR2 = %02x\n", machine().describe_context(), data);
+ m_r[TIFR2] &= ~(data & TIFR2_MASK);
+ update_interrupt(INTIDX_OCF2A);
+ update_interrupt(INTIDX_OCF2B);
+ update_interrupt(INTIDX_TOV2);
+}
- case AVR8_REGIDX_TIFR0:
- LOGMASKED(LOG_TIMER0, "%s: TIFR0 = %02x\n", machine().describe_context(), data);
- m_r[AVR8_REGIDX_TIFR0] &= ~(data & AVR8_TIFR0_MASK);
- update_interrupt(AVR8_INTIDX_OCF0A);
- update_interrupt(AVR8_INTIDX_OCF0B);
- update_interrupt(AVR8_INTIDX_TOV0);
- break;
+template <int NumTimers>
+void avr8_device<NumTimers>::gtccr_w(uint8_t data)
+{
+ if (data & GTCCR_PSRASY_MASK)
+ {
+ data &= ~GTCCR_PSRASY_MASK;
+ m_timer_prescale_count[2] = 0;
+ }
+}
- case AVR8_REGIDX_TCNT0:
- AVR8_TCNT0 = data;
- break;
+template <int NumTimers>
+void avr8_device<NumTimers>::eecr_w(uint8_t data)
+{
+ m_r[EECR] = data & EECR_MASK;
- case AVR8_REGIDX_TIFR1:
- LOGMASKED(LOG_TIMER1, "%s: TIFR1 = %02x\n", machine().describe_context(), data);
- m_r[AVR8_REGIDX_TIFR1] &= ~(data & AVR8_TIFR1_MASK);
- update_interrupt(AVR8_INTIDX_ICF1);
- update_interrupt(AVR8_INTIDX_OCF1A);
- update_interrupt(AVR8_INTIDX_OCF1B);
- update_interrupt(AVR8_INTIDX_TOV1);
- break;
+ if (data & EECR_EERE_MASK)
+ {
+ uint16_t addr = (m_r[EEARH] & EEARH_MASK) << 8;
+ addr |= m_r[EEARL];
+ m_r[EEDR] = m_eeprom[addr];
+ LOGMASKED(LOG_EEPROM, "%s: EEPROM read @ %04x data = %02x\n", machine().describe_context(), addr, m_eeprom[addr]);
+ }
+ if ((data & EECR_EEPE_MASK) && (data & EECR_EEMPE_MASK))
+ {
+ uint16_t addr = (m_r[EEARH] & EEARH_MASK) << 8;
+ addr |= m_r[EEARL];
+ m_eeprom[addr] = m_r[EEDR];
+ LOGMASKED(LOG_EEPROM, "%s: EEPROM write @ %04x data = %02x ('%c')\n", machine().describe_context(), addr, m_eeprom[addr], m_eeprom[addr] >= 0x21 ? m_eeprom[addr] : ' ');
- case AVR8_REGIDX_TIFR2:
- LOGMASKED(LOG_TIMER2, "%s: TIFR2 = %02x\n", machine().describe_context(), data);
- m_r[AVR8_REGIDX_TIFR2] &= ~(data & AVR8_TIFR2_MASK);
- update_interrupt(AVR8_INTIDX_OCF2A);
- update_interrupt(AVR8_INTIDX_OCF2B);
- update_interrupt(AVR8_INTIDX_TOV2);
- break;
+ // Indicate that we've finished writing a value to the EEPROM.
+ // TODO: this should only happen after a certain dalay.
+ m_r[EECR] = data & ~EECR_EEPE_MASK;
+ }
+}
- case AVR8_REGIDX_GTCCR:
- if (data & AVR8_GTCCR_PSRASY_MASK)
- {
- data &= ~AVR8_GTCCR_PSRASY_MASK;
- m_timer_prescale_count[2] = 0;
- }
- break;
+template <int NumTimers>
+void avr8_device<NumTimers>::gpior0_w(uint8_t data)
+{
+ LOGMASKED(LOG_GPIO, "%s: GPIOR0 Write: %02x\n", machine().describe_context(), data);
+ m_r[GPIOR0] = data;
+}
- // EEPROM registers
- case AVR8_REGIDX_EEARL:
- case AVR8_REGIDX_EEARH:
- case AVR8_REGIDX_EEDR:
- m_r[offset] = data;
- break;
+template <int NumTimers>
+void avr8_device<NumTimers>::gpior1_w(uint8_t data)
+{
+ LOGMASKED(LOG_GPIO, "%s: GPIOR1 Write: %02x\n", machine().describe_context(), data);
+ m_r[GPIOR1] = data;
+}
- case AVR8_REGIDX_EECR:
- m_r[offset] = data;
+template <int NumTimers>
+void avr8_device<NumTimers>::gpior2_w(uint8_t data)
+{
+ LOGMASKED(LOG_GPIO, "%s: GPIOR2 Write: %02x\n", machine().describe_context(), data);
+ m_r[GPIOR2] = data;
+}
- if (data & AVR8_EECR_EERE_MASK)
- {
- uint16_t addr = (m_r[AVR8_REGIDX_EEARH] & AVR8_EEARH_MASK) << 8;
- addr |= m_r[AVR8_REGIDX_EEARL];
- m_r[AVR8_REGIDX_EEDR] = m_eeprom[addr];
- LOGMASKED(LOG_EEPROM, "%s: EEPROM read @ %04x data = %02x\n", machine().describe_context(), addr, m_eeprom[addr]);
- }
- if ((data & AVR8_EECR_EEPE_MASK) && (data & AVR8_EECR_EEMPE_MASK))
- {
- uint16_t addr = (m_r[AVR8_REGIDX_EEARH] & AVR8_EEARH_MASK) << 8;
- addr |= m_r[AVR8_REGIDX_EEARL];
- m_eeprom[addr] = m_r[AVR8_REGIDX_EEDR];
- LOGMASKED(LOG_EEPROM, "%s: EEPROM write @ %04x data = %02x ('%c')\n", machine().describe_context(), addr, m_eeprom[addr], m_eeprom[addr]);
-
- // Indicate that we've finished writing a value to the EEPROM.
- // TODO: this should only happen after a certain dalay.
- m_r[offset] = data & ~AVR8_EECR_EEPE_MASK;
- }
- break;
+template <int NumTimers>
+void avr8_device<NumTimers>::spsr_w(uint8_t data)
+{
+ change_spsr(data);
+}
- case AVR8_REGIDX_GPIOR0:
- LOGMASKED(LOG_GPIO, "%s: GPIOR0 Write: %02x\n", machine().describe_context(), data);
- m_r[AVR8_REGIDX_GPIOR0] = data;
- break;
+template <int NumTimers>
+void avr8_device<NumTimers>::spcr_w(uint8_t data)
+{
+ change_spcr(data);
+}
- case AVR8_REGIDX_GPIOR1:
- LOGMASKED(LOG_GPIO, "%s: GPIOR1 Write: %02x\n", machine().describe_context(), data);
- m_r[offset] = data;
- break;
+template <int NumTimers>
+void avr8_device<NumTimers>::spdr_w(uint8_t data)
+{
+ m_r[SPDR] = data;
+ m_spi_active = true;
+ m_spi_prescale_countdown = 7;
+ m_spi_prescale_count = 0;
+}
- case AVR8_REGIDX_GPIOR2:
- LOGMASKED(LOG_GPIO, "%s: GPIOR2 Write: %02x\n", machine().describe_context(), data);
- m_r[offset] = data;
- break;
+template <int NumTimers>
+void avr8_device<NumTimers>::wdtcsr_w(uint8_t data)
+{
+ LOGMASKED(LOG_WDOG, "%s: (not yet implemented) WDTCSR = %02x\n", machine().describe_context(), data);
+}
- case AVR8_REGIDX_SPSR:
- change_spsr(data);
- break;
+template <int NumTimers>
+void avr8_device<NumTimers>::clkpr_w(uint8_t data)
+{
+ LOGMASKED(LOG_CLOCK, "%s: (not yet implemented) CLKPR = %02x\n", machine().describe_context(), data);
+}
- case AVR8_REGIDX_SPCR:
- change_spcr(data);
- break;
+template <int NumTimers>
+void avr8_device<NumTimers>::prr0_w(uint8_t data)
+{
+ LOGMASKED(LOG_POWER, "%s: (not yet implemented) PRR0 = %02x\n", machine().describe_context(), data);
+}
+
+template <int NumTimers>
+void avr8_device<NumTimers>::prr1_w(uint8_t data)
+{
+ LOGMASKED(LOG_POWER, "%s: (not yet implemented) PRR1 = %02x\n", machine().describe_context(), data);
+}
+
+template <int NumTimers>
+void avr8_device<NumTimers>::osccal_w(uint8_t data)
+{
+ LOGMASKED(LOG_POWER, "%s: (not yet implemented) OSCCAL = %02x\n", machine().describe_context(), data);
+}
- case AVR8_REGIDX_SPDR:
+template <int NumTimers>
+void avr8_device<NumTimers>::pcicr_w(uint8_t data)
+{
+ LOGMASKED(LOG_POWER, "%s: (not yet implemented) PCICR = %02x\n", machine().describe_context(), data);
+}
+
+template <int NumTimers>
+void avr8_device<NumTimers>::eicra_w(uint8_t data)
+{
+ LOGMASKED(LOG_POWER, "%s: (not yet implemented) EICRA = %02x\n", machine().describe_context(), data);
+}
+
+template <int NumTimers>
+void avr8_device<NumTimers>::eicrb_w(uint8_t data)
+{
+ LOGMASKED(LOG_POWER, "%s: (not yet implemented) EICRB = %02x\n", machine().describe_context(), data);
+}
+
+template <int NumTimers>
+void avr8_device<NumTimers>::pcmsk0_w(uint8_t data)
+{
+ LOGMASKED(LOG_POWER, "%s: (not yet implemented) PCMSK0 = %02x\n", machine().describe_context(), data);
+}
+
+template <int NumTimers>
+void avr8_device<NumTimers>::pcmsk1_w(uint8_t data)
+{
+ LOGMASKED(LOG_POWER, "%s: (not yet implemented) PCMSK1 = %02x\n", machine().describe_context(), data);
+}
+
+template <int NumTimers>
+void avr8_device<NumTimers>::pcmsk2_w(uint8_t data)
+{
+ LOGMASKED(LOG_POWER, "%s: (not yet implemented) PCMSK2 = %02x\n", machine().describe_context(), data);
+}
+
+template <int NumTimers>
+void avr8_device<NumTimers>::timsk0_w(uint8_t data)
+{
+ LOGMASKED(LOG_TIMER0, "%s: TIMSK0 = %02x\n", machine().describe_context(), data);
+ m_r[TIMSK0] = data;
+ update_interrupt(INTIDX_OCF0A);
+ update_interrupt(INTIDX_OCF0B);
+ update_interrupt(INTIDX_TOV0);
+}
+
+template <int NumTimers>
+void avr8_device<NumTimers>::timsk1_w(uint8_t data)
+{
+ LOGMASKED(LOG_TIMER1, "%s: TIMSK1 = %02x\n", machine().describe_context(), data);
+ m_r[TIMSK1] = data;
+ update_interrupt(INTIDX_ICF1);
+ update_interrupt(INTIDX_OCF1A);
+ update_interrupt(INTIDX_OCF1B);
+ update_interrupt(INTIDX_TOV1);
+}
+
+template <int NumTimers>
+void avr8_device<NumTimers>::timsk2_w(uint8_t data)
+{
+ LOGMASKED(LOG_TIMER2, "%s: TIMSK2 = %02x\n", machine().describe_context(), data);
+ m_r[TIMSK2] = data;
+ update_interrupt(INTIDX_OCF2A);
+ update_interrupt(INTIDX_OCF2B);
+ update_interrupt(INTIDX_TOV2);
+}
+
+template <int NumTimers>
+void avr8_device<NumTimers>::timsk3_w(uint8_t data)
+{
+ LOGMASKED(LOG_TIMER3, "%s: TIMSK3 = %02x\n", machine().describe_context(), data);
+ m_r[TIMSK3] = data;
+ update_interrupt(INTIDX_OCF3A);
+ update_interrupt(INTIDX_OCF3B);
+ update_interrupt(INTIDX_TOV3);
+}
+
+template <int NumTimers>
+void avr8_device<NumTimers>::timsk4_w(uint8_t data)
+{
+ LOGMASKED(LOG_TIMER4, "%s: TIMSK4 = %02x\n", machine().describe_context(), data);
+ m_r[TIMSK4] = data;
+ update_interrupt(INTIDX_OCF4A);
+ update_interrupt(INTIDX_OCF4B);
+ update_interrupt(INTIDX_TOV4);
+}
+
+template <int NumTimers>
+void avr8_device<NumTimers>::timsk5_w(uint8_t data)
+{
+ LOGMASKED(LOG_TIMER5, "%s: TIMSK5 = %02x\n", machine().describe_context(), data);
+ m_r[TIMSK5] = data;
+ update_interrupt(INTIDX_OCF5A);
+ update_interrupt(INTIDX_OCF5B);
+ update_interrupt(INTIDX_TOV5);
+}
+
+template <int NumTimers>
+void avr8_device<NumTimers>::xmcra_w(uint8_t data)
+{
+ LOGMASKED(LOG_EXTMEM, "%s: (not yet implemented) XMCRA = %02x\n", machine().describe_context(), data);
+}
+
+template <int NumTimers>
+void avr8_device<NumTimers>::xmcrb_w(uint8_t data)
+{
+ LOGMASKED(LOG_EXTMEM, "%s: (not yet implemented) XMCRB = %02x\n", machine().describe_context(), data);
+}
+
+template <int NumTimers>
+uint8_t avr8_device<NumTimers>::adcl_r()
+{
+ if (!machine().side_effects_disabled())
+ m_adc_hold = true;
+ if (ADMUX_ADLAR)
+ return (m_adc_data & 0x03) << 6;
+ else
+ return uint8_t(m_adc_data);
+}
+
+template <int NumTimers>
+void avr8_device<NumTimers>::adcl_w(uint8_t data)
+{
+ LOGMASKED(LOG_ADC, "%s: ADCL = %02x\n", machine().describe_context(), data);
+}
+
+template <int NumTimers>
+uint8_t avr8_device<NumTimers>::adch_r()
+{
+ uint8_t const result = ADMUX_ADLAR ? BIT(m_adc_data, 2, 8) : BIT(m_adc_data, 8, 2);
+ if (!machine().side_effects_disabled())
{
- m_r[AVR8_REGIDX_SPDR] = data;
- m_spi_active = true;
- m_spi_prescale_countdown = 7;
- m_spi_prescale_count = 0;
- break;
+ m_adc_data = m_adc_result;
+ m_adc_hold = false;
}
+ return result;
+}
- case AVR8_REGIDX_WDTCSR:
- LOGMASKED(LOG_WDOG, "%s: (not yet implemented) WDTCSR = %02x\n", machine().describe_context(), data);
- break;
+template <int NumTimers>
+void avr8_device<NumTimers>::adch_w(uint8_t data)
+{
+ LOGMASKED(LOG_ADC, "%s: ADCH = %02x\n", machine().describe_context(), data);
+}
- case AVR8_REGIDX_CLKPR:
- LOGMASKED(LOG_CLOCK, "%s: (not yet implemented) CLKPR = %02x\n", machine().describe_context(), data);
- break;
+template <int NumTimers>
+void avr8_device<NumTimers>::adcsra_w(uint8_t data)
+{
+ LOGMASKED(LOG_ADC, "%s: ADCSRA = %02x\n", machine().describe_context(), data);
- case AVR8_REGIDX_PRR0:
- LOGMASKED(LOG_POWER, "%s: (not yet implemented) PRR0 = %02x\n", machine().describe_context(), data);
- break;
+ // set auto trigger enable, interrupt enable, and prescaler directly
+ m_r[ADCSRA] &= ~(ADCSRA_ADATE_MASK | ADCSRA_ADIE_MASK | ADCSRA_ADPS_MASK);
+ m_r[ADCSRA] |= data & (ADCSRA_ADATE_MASK | ADCSRA_ADIE_MASK | ADCSRA_ADPS_MASK);
- case AVR8_REGIDX_PRR1:
- LOGMASKED(LOG_POWER, "%s: (not yet implemented) PRR1 = %02x\n", machine().describe_context(), data);
- break;
+ // check enable bit
+ if (!(data & ADCSRA_ADEN_MASK))
+ {
+ // disable ADC, terminate any conversion in progress
+ m_r[ADCSRA] &= ~(ADCSRA_ADEN_MASK | ADCSRA_ADSC_MASK);
+ m_adc_timer->reset();
+ }
+ else
+ {
+ // first conversion after initial enable takes longer
+ if (!ADCSRA_ADEN)
+ {
+ m_adc_first = true;
+ m_r[ADCSRA] |= ADCSRA_ADEN_MASK;
+ }
- case AVR8_REGIDX_OSCCAL:
- LOGMASKED(LOG_OSC, "%s: (not yet implemented) OSCCAL = %02x\n", machine().describe_context(), data);
- break;
+ // trigger conversion if necessary
+ if (!ADCSRA_ADSC && (data & ADCSRA_ADSC_MASK))
+ adc_start_conversion();
+ }
- case AVR8_REGIDX_PCICR:
- LOGMASKED(LOG_PINCHG, "%s: (not yet implemented) PCICR = %02x\n", machine().describe_context(), data);
- break;
+ // writing with ADIF set clears the interrupt flag manually
+ if (data & ADCSRA_ADIF_MASK)
+ m_r[ADCSRA] &= ~ADCSRA_ADIF_MASK;
- case AVR8_REGIDX_EICRA:
- LOGMASKED(LOG_GPIO, "%s: (not yet implemented) EICRA = %02x\n", machine().describe_context(), data);
- break;
+ if (ADCSRA_ADIE)
+ logerror("%s: Unimplemented ADC interrupt enabled\n");
+}
- case AVR8_REGIDX_EICRB:
- LOGMASKED(LOG_GPIO, "%s: (not yet implemented) EICRB = %02x\n", machine().describe_context(), data);
- break;
+template <int NumTimers>
+void avr8_device<NumTimers>::adcsrb_w(uint8_t data)
+{
+ LOGMASKED(LOG_ADC, "%s: ADCSRB = %02x\n", machine().describe_context(), data);
+ m_r[ADCSRB] = data & (ADCSRB_ACME_MASK | ADCSRB_ADTS_MASK);
+ if (ADCSRB_ADTS != 0)
+ logerror("%s: Unimplemented ADC auto trigger source %X selected\n", machine().describe_context(), ADCSRB_ADTS);
+}
- case AVR8_REGIDX_PCMSK0:
- LOGMASKED(LOG_PINCHG, "%s: (not yet implemented) PCMSK0 = %02x\n", machine().describe_context(), data);
- break;
+template <int NumTimers>
+void avr8_device<NumTimers>::admux_w(uint8_t data)
+{
+ LOGMASKED(LOG_ADC, "%s: ADMUX = %02x\n", machine().describe_context(), data);
+ m_r[ADMUX] = data & (ADMUX_REFS_MASK | ADMUX_ADLAR_MASK | ADMUX_MUX_MASK);
+}
- case AVR8_REGIDX_PCMSK1:
- LOGMASKED(LOG_PINCHG, "%s: (not yet implemented) PCMSK1 = %02x\n", machine().describe_context(), data);
- break;
+template <int NumTimers>
+void avr8_device<NumTimers>::didr0_w(uint8_t data)
+{
+ LOGMASKED(LOG_DIGINPUT, "%s: (not yet implemented) DIDR0 = %02x\n", machine().describe_context(), data);
+}
- case AVR8_REGIDX_PCMSK2:
- LOGMASKED(LOG_PINCHG, "%s: (not yet implemented) PCMSK2 = %02x\n", machine().describe_context(), data);
- break;
+template <int NumTimers>
+void avr8_device<NumTimers>::didr1_w(uint8_t data)
+{
+ LOGMASKED(LOG_DIGINPUT, "%s: (not yet implemented) DIDR1 = %02x\n", machine().describe_context(), data);
+}
- case AVR8_REGIDX_TIMSK0:
- LOGMASKED(LOG_TIMER0, "%s: TIMSK0 = %02x\n", machine().describe_context(), data);
- m_r[AVR8_REGIDX_TIMSK0] = data;
- update_interrupt(AVR8_INTIDX_OCF0A);
- update_interrupt(AVR8_INTIDX_OCF0B);
- update_interrupt(AVR8_INTIDX_TOV0);
- break;
+template <int NumTimers>
+void avr8_device<NumTimers>::didr2_w(uint8_t data)
+{
+ LOGMASKED(LOG_DIGINPUT, "%s: (not yet implemented) DIDR2 = %02x\n", machine().describe_context(), data);
+}
- case AVR8_REGIDX_TIMSK1:
- LOGMASKED(LOG_TIMER1, "%s: TIMSK1 = %02x\n", machine().describe_context(), data);
- m_r[AVR8_REGIDX_TIMSK1] = data;
- update_interrupt(AVR8_INTIDX_ICF1);
- update_interrupt(AVR8_INTIDX_OCF1A);
- update_interrupt(AVR8_INTIDX_OCF1B);
- update_interrupt(AVR8_INTIDX_TOV1);
- break;
+template <int NumTimers>
+void avr8_device<NumTimers>::tccr1a_w(uint8_t data)
+{
+ LOGMASKED(LOG_TIMER1, "%s: TCCR1A = %02x\n", machine().describe_context(), data);
+ const uint8_t oldtccr = m_r[TCCR1A];
+ const uint8_t newtccr = data;
+ const uint8_t changed = newtccr ^ oldtccr;
+ m_r[TCCR1A] = newtccr;
- case AVR8_REGIDX_TIMSK2:
- LOGMASKED(LOG_TIMER2, "%s: TIMSK2 = %02x\n", machine().describe_context(), data);
- m_r[AVR8_REGIDX_TIMSK2] = data;
- update_interrupt(AVR8_INTIDX_OCF2A);
- update_interrupt(AVR8_INTIDX_OCF2B);
- update_interrupt(AVR8_INTIDX_TOV2);
- break;
+ if (changed & TCCR1A_WGM1_10_MASK)
+ {
+ update_timer_waveform_gen_mode(1, WGM1);
+ }
- case AVR8_REGIDX_TIMSK3:
- LOGMASKED(LOG_TIMER3, "%s: TIMSK3 = %02x\n", machine().describe_context(), data);
- m_r[AVR8_REGIDX_TIMSK3] = data;
- update_interrupt(AVR8_INTIDX_OCF3A);
- update_interrupt(AVR8_INTIDX_OCF3B);
- update_interrupt(AVR8_INTIDX_TOV3);
- break;
+ m_timer1_tick = m_timer1_ticks[(WGM1 << 4) | ((m_r[TCCR1A] & TCCR1A_COM1AB_MASK) >> TCCR1A_COM1AB_SHIFT)];
+}
- case AVR8_REGIDX_TIMSK4:
- LOGMASKED(LOG_TIMER4, "%s: TIMSK4 = %02x\n", machine().describe_context(), data);
- m_r[AVR8_REGIDX_TIMSK4] = data;
- update_interrupt(AVR8_INTIDX_OCF4A);
- update_interrupt(AVR8_INTIDX_OCF4B);
- update_interrupt(AVR8_INTIDX_TOV4);
- break;
+template <int NumTimers>
+void avr8_device<NumTimers>::tccr1b_w(uint8_t data)
+{
+ LOGMASKED(LOG_TIMER1, "%s: TCCR1B = %02x\n", machine().describe_context(), data);
+ const uint8_t oldtccr = m_r[TCCR1B];
+ const uint8_t newtccr = data;
+ const uint8_t changed = newtccr ^ oldtccr;
+ const uint8_t oldcs = m_r[TCCR1B] & TCCR1B_CS_MASK;
- case AVR8_REGIDX_TIMSK5:
- LOGMASKED(LOG_TIMER5, "%s: TIMSK5 = %02x\n", machine().describe_context(), data);
- m_r[AVR8_REGIDX_TIMSK5] = data;
- update_interrupt(AVR8_INTIDX_OCF5A);
- update_interrupt(AVR8_INTIDX_OCF5B);
- update_interrupt(AVR8_INTIDX_TOV5);
- break;
+ m_r[TCCR1B] = newtccr;
- case AVR8_REGIDX_XMCRA:
- LOGMASKED(LOG_EXTMEM, "%s: (not yet implemented) XMCRA = %02x\n", machine().describe_context(), data);
- break;
+ if (changed & TCCR1B_ICNC1_MASK)
+ {
+ update_timer1_input_noise_canceler();
+ }
- case AVR8_REGIDX_XMCRB:
- LOGMASKED(LOG_EXTMEM, "%s: (not yet implemented) XMCRB = %02x\n", machine().describe_context(), data);
- break;
+ if (changed & TCCR1B_ICES1_MASK)
+ {
+ update_timer1_input_edge_select();
+ }
- case AVR8_REGIDX_ADCL:
- LOGMASKED(LOG_ADC, "%s: (not yet implemented) ADCL = %02x\n", machine().describe_context(), data);
- break;
+ if (changed & TCCR1B_WGM1_32_MASK)
+ {
+ update_timer_waveform_gen_mode(1, WGM1);
+ }
- case AVR8_REGIDX_ADCH:
- LOGMASKED(LOG_ADC, "%s: (not yet implemented) ADCH = %02x\n", machine().describe_context(), data);
- break;
+ if (changed & TCCR1B_CS_MASK)
+ {
+ update_timer_clock_source<1>(TIMER1_CLOCK_SELECT, oldcs);
+ }
- case AVR8_REGIDX_ADCSRA:
- LOGMASKED(LOG_ADC, "%s: (not yet implemented) ADCSRA = %02x\n", machine().describe_context(), data);
- break;
+ m_timer1_tick = m_timer1_ticks[(WGM1 << 4) | ((m_r[TCCR1A] & TCCR1A_COM1AB_MASK) >> TCCR1A_COM1AB_SHIFT)];
+}
- case AVR8_REGIDX_ADCSRB:
- LOGMASKED(LOG_ADC, "%s: (not yet implemented) ADCSRB = %02x\n", machine().describe_context(), data);
- break;
+template <int NumTimers>
+void avr8_device<NumTimers>::tccr1c_w(uint8_t data)
+{
+ LOGMASKED(LOG_TIMER1, "%s: (not yet implemented) TCCR1C = %02x\n", machine().describe_context(), data);
+}
- case AVR8_REGIDX_ADMUX:
- LOGMASKED(LOG_ADC, "%s: (not yet implemented) ADMUX = %02x\n", machine().describe_context(), data);
- break;
+template <int NumTimers>
+void avr8_device<NumTimers>::icr1l_w(uint8_t data)
+{
+ m_r[ICR1L] = data;
+}
- case AVR8_REGIDX_DIDR0:
- LOGMASKED(LOG_DIGINPUT, "%s: (not yet implemented) DIDR0 = %02x\n", machine().describe_context(), data);
- break;
+template <int NumTimers>
+void avr8_device<NumTimers>::icr1h_w(uint8_t data)
+{
+ m_r[ICR1H] = data;
+}
- case AVR8_REGIDX_DIDR1:
- LOGMASKED(LOG_DIGINPUT, "%s: (not yet implemented) DIDR1 = %02x\n", machine().describe_context(), data);
- break;
+template <int NumTimers>
+void avr8_device<NumTimers>::ocr1al_w(uint8_t data)
+{
+ LOGMASKED(LOG_TIMER1, "%s: OCR1AL = %02x\n", machine().describe_context(), data);
+ update_ocr1((OCR1A & 0xff00) | data, AVR8_REG_A);
+}
- case AVR8_REGIDX_DIDR2:
- LOGMASKED(LOG_DIGINPUT, "%s: (not yet implemented) DIDR2 = %02x\n", machine().describe_context(), data);
- break;
+template <int NumTimers>
+void avr8_device<NumTimers>::ocr1ah_w(uint8_t data)
+{
+ LOGMASKED(LOG_TIMER1, "%s: OCR1AH = %02x\n", machine().describe_context(), data);
+ update_ocr1((OCR1A & 0x00ff) | (data << 8), AVR8_REG_A);
+}
- case AVR8_REGIDX_TCCR1A:
- LOGMASKED(LOG_TIMER1, "%s: TCCR1A = %02x\n", machine().describe_context(), data);
- changed_tccr1a(data);
- break;
+template <int NumTimers>
+void avr8_device<NumTimers>::ocr1bl_w(uint8_t data)
+{
+ LOGMASKED(LOG_TIMER1, "%s: OCR1BL = %02x\n", machine().describe_context(), data);
+ update_ocr1((OCR1B & 0xff00) | data, AVR8_REG_B);
+}
- case AVR8_REGIDX_TCCR1B:
- LOGMASKED(LOG_TIMER1, "%s: TCCR1B = %02x\n", machine().describe_context(), data);
- changed_tccr1b(data);
- break;
+template <int NumTimers>
+void avr8_device<NumTimers>::ocr1bh_w(uint8_t data)
+{
+ LOGMASKED(LOG_TIMER1, "%s: OCR1BH = %02x\n", machine().describe_context(), data);
+ update_ocr1((OCR1B & 0x00ff) | (data << 8), AVR8_REG_B);
+}
- case AVR8_REGIDX_TCCR1C:
- LOGMASKED(LOG_TIMER1, "%s: (not yet implemented) TCCR1C = %02x\n", machine().describe_context(), data);
- break;
+template <int NumTimers>
+void avr8_device<NumTimers>::ocr1cl_w(uint8_t data)
+{
+ LOGMASKED(LOG_TIMER1, "%s: OCR1CL = %02x\n", machine().describe_context(), data);
+ update_ocr1((OCR1C & 0xff00) | data, AVR8_REG_C);
+}
- case AVR8_REGIDX_TCNT1L:
- m_timer1_count = (m_timer1_count & 0xff00) | data;
- break;
+template <int NumTimers>
+void avr8_device<NumTimers>::ocr1ch_w(uint8_t data)
+{
+ LOGMASKED(LOG_TIMER1, "%s: OCR1CH = %02x\n", machine().describe_context(), data);
+ update_ocr1((OCR1C & 0x00ff) | (data << 8), AVR8_REG_C);
+}
- case AVR8_REGIDX_TCNT1H:
- m_timer1_count = (m_timer1_count & 0x00ff) | (data << 8);
- break;
+template <int NumTimers>
+void avr8_device<NumTimers>::tccr2a_w(uint8_t data)
+{
+ LOGMASKED(LOG_TIMER2, "%s: TCCR2A = %02x\n", machine().describe_context(), data);
+ const uint8_t oldtccr = m_r[TCCR2A];
+ const uint8_t newtccr = data;
+ const uint8_t changed = newtccr ^ oldtccr;
- case AVR8_REGIDX_ICR1L:
- AVR8_ICR1L = data;
- break;
+ m_r[TCCR2A] = data;
- case AVR8_REGIDX_ICR1H:
- AVR8_ICR1H = data;
- break;
+ if (changed & TCCR2A_WGM2_10_MASK)
+ {
+ update_timer_waveform_gen_mode(2, WGM2);
+ }
- case AVR8_REGIDX_OCR1AL:
- LOGMASKED(LOG_TIMER1, "%s: OCR1AL = %02x\n", machine().describe_context(), data);
- update_ocr1((AVR8_OCR1A & 0xff00) | data, AVR8_REG_A);
- break;
+ m_timer2_tick = m_timer2_ticks[((m_r[TCCR2B] & TCCR2B_WGM2_2_MASK) >> 1) | (m_r[TCCR2A] & TCCR2A_WGM2_10_MASK)];
+}
- case AVR8_REGIDX_OCR1AH:
- LOGMASKED(LOG_TIMER1, "%s: OCR1AH = %02x\n", machine().describe_context(), data);
- update_ocr1((AVR8_OCR1A & 0x00ff) | (data << 8), AVR8_REG_A);
- break;
+template <int NumTimers>
+void avr8_device<NumTimers>::tccr2b_w(uint8_t data)
+{
+ LOGMASKED(LOG_TIMER2, "%s: TCCR2B = %02x\n", machine().describe_context(), data);
+ const uint8_t oldtccr = m_r[TCCR2B];
+ const uint8_t newtccr = data;
+ const uint8_t changed = newtccr ^ oldtccr;
+ const uint8_t oldcs = m_r[TCCR2B] & TCCR2B_CS_MASK;
- case AVR8_REGIDX_OCR1BL:
- LOGMASKED(LOG_TIMER1, "%s: OCR1BL = %02x\n", machine().describe_context(), data);
- update_ocr1((AVR8_OCR1B & 0xff00) | data, AVR8_REG_B);
- break;
+ m_r[TCCR2B] = data;
- case AVR8_REGIDX_OCR1BH:
- LOGMASKED(LOG_TIMER1, "%s: OCR1BH = %02x\n", machine().describe_context(), data);
- update_ocr1((AVR8_OCR1B & 0x00ff) | (data << 8), AVR8_REG_B);
- break;
+ if (changed & TCCR2B_FOC2A_MASK)
+ {
+ timer2_force_output_compare(AVR8_REG_A);
+ }
- case AVR8_REGIDX_OCR1CL:
- LOGMASKED(LOG_TIMER1, "%s: OCR1CL = %02x\n", machine().describe_context(), data);
- update_ocr1((AVR8_OCR1C & 0xff00) | data, AVR8_REG_C);
- break;
+ if (changed & TCCR2B_FOC2B_MASK)
+ {
+ timer2_force_output_compare(AVR8_REG_B);
+ }
- case AVR8_REGIDX_OCR1CH:
- LOGMASKED(LOG_TIMER1, "%s: OCR1CH = %02x\n", machine().describe_context(), data);
- update_ocr1((AVR8_OCR1C & 0x00ff) | (data << 8), AVR8_REG_C);
- break;
+ if (changed & TCCR2B_WGM2_2_MASK)
+ {
+ update_timer_waveform_gen_mode(2, WGM2);
+ }
- case AVR8_REGIDX_TCCR2A:
- LOGMASKED(LOG_TIMER2, "%s: TCCR2A = %02x\n", machine().describe_context(), data);
- changed_tccr2a(data);
- break;
+ if (changed & TCCR2B_CS_MASK)
+ {
+ update_timer_clock_source<2>(TIMER2_CLOCK_SELECT, oldcs);
+ }
- case AVR8_REGIDX_TCCR2B:
- LOGMASKED(LOG_TIMER2, "%s: TCCR2B = %02x\n", machine().describe_context(), data);
- changed_tccr2b(data);
- break;
+ m_timer2_tick = m_timer2_ticks[((m_r[TCCR2B] & TCCR2B_WGM2_2_MASK) >> 1) | (m_r[TCCR2A] & TCCR2A_WGM2_10_MASK)];
+}
- case AVR8_REGIDX_TCNT2:
- AVR8_TCNT2 = data;
- break;
+template <int NumTimers>
+void avr8_device<NumTimers>::tcnt2_w(uint8_t data)
+{
+ m_r[TCNT2] = data;
+}
- case AVR8_REGIDX_OCR2A:
- update_ocr2(data, AVR8_REG_A);
- break;
+template <int NumTimers>
+void avr8_device<NumTimers>::ocr2a_w(uint8_t data)
+{
+ update_ocr2(data, AVR8_REG_A);
+}
- case AVR8_REGIDX_OCR2B:
- update_ocr2(data, AVR8_REG_B);
- break;
+template <int NumTimers>
+void avr8_device<NumTimers>::ocr2b_w(uint8_t data)
+{
+ update_ocr2(data, AVR8_REG_B);
+}
- case AVR8_REGIDX_TCCR3A:
- LOGMASKED(LOG_TIMER3, "%s: TCCR3A = %02x\n", machine().describe_context(), data);
- changed_tccr3a(data);
- break;
+template <int NumTimers>
+void avr8_device<NumTimers>::tccr3a_w(uint8_t data)
+{
+ LOGMASKED(LOG_TIMER3, "%s: (not yet implemented) TCCR3A = %02x\n", machine().describe_context(), data);
+ // TODO
+ // AVR8_TCCR3A = data;
+}
- case AVR8_REGIDX_TCCR3B:
- LOGMASKED(LOG_TIMER3, "%s: TCCR3B = %02x\n", machine().describe_context(), data);
- changed_tccr3b(data);
- break;
+template <int NumTimers>
+void avr8_device<NumTimers>::tccr3b_w(uint8_t data)
+{
+ LOGMASKED(LOG_TIMER3, "%s: (not yet implemented) TCCR3B = %02x\n", machine().describe_context(), data);
+}
- case AVR8_REGIDX_TCCR3C:
- LOGMASKED(LOG_TIMER3, "%s: TCCR3C = %02x\n", machine().describe_context(), data);
- changed_tccr3c(data);
- break;
+template <int NumTimers>
+void avr8_device<NumTimers>::tccr3c_w(uint8_t data)
+{
+ LOGMASKED(LOG_TIMER3, "%s: (not yet implemented) TCCR3C = %02x\n", machine().describe_context(), data);
+}
- case AVR8_REGIDX_TCNT3L:
- AVR8_TCNT3L = data;
- break;
+template <int NumTimers>
+void avr8_device<NumTimers>::icr3l_w(uint8_t data)
+{
+ m_r[ICR3L] = data;
+}
- case AVR8_REGIDX_TCNT3H:
- AVR8_TCNT3H = data;
- break;
+template <int NumTimers>
+void avr8_device<NumTimers>::icr3h_w(uint8_t data)
+{
+ m_r[ICR3H] = data;
+}
- case AVR8_REGIDX_ICR3L:
- AVR8_ICR3L = data;
- break;
+template <int NumTimers>
+void avr8_device<NumTimers>::ocr3al_w(uint8_t data)
+{
+ m_r[OCR3AL] = data;
+}
- case AVR8_REGIDX_ICR3H:
- AVR8_ICR3H = data;
- break;
+template <int NumTimers>
+void avr8_device<NumTimers>::ocr3ah_w(uint8_t data)
+{
+ m_r[OCR3AH] = data;
+}
- case AVR8_REGIDX_OCR3AL:
- AVR8_OCR3AL = data;
- break;
+template <int NumTimers>
+void avr8_device<NumTimers>::ocr3bl_w(uint8_t data)
+{
+ m_r[OCR3BL] = data;
+}
- case AVR8_REGIDX_OCR3AH:
- AVR8_OCR3AH = data;
- break;
+template <int NumTimers>
+void avr8_device<NumTimers>::ocr3bh_w(uint8_t data)
+{
+ m_r[OCR3BH] = data;
+}
- case AVR8_REGIDX_OCR3BL:
- AVR8_OCR3BL = data;
- break;
+template <int NumTimers>
+void avr8_device<NumTimers>::ocr3cl_w(uint8_t data)
+{
+ m_r[OCR3CL] = data;
+}
- case AVR8_REGIDX_OCR3BH:
- AVR8_OCR3BH = data;
- break;
+template <int NumTimers>
+void avr8_device<NumTimers>::ocr3ch_w(uint8_t data)
+{
+ m_r[OCR3CH] = data;
+}
- case AVR8_REGIDX_OCR3CL:
- AVR8_OCR3CL = data;
- break;
+template <int NumTimers>
+void avr8_device<NumTimers>::tccr4a_w(uint8_t data)
+{
+ LOGMASKED(LOG_TIMER4, "%s: TCCR4A = %02x\n", machine().describe_context(), data);
+ const uint8_t oldtccr = m_r[TCCR4A];
+ const uint8_t newtccr = data;
+ const uint8_t changed = newtccr ^ oldtccr;
- case AVR8_REGIDX_OCR3CH:
- AVR8_OCR3CH = data;
- break;
+ m_r[TCCR4A] = data;
- case AVR8_REGIDX_TCCR4A:
- LOGMASKED(LOG_TIMER4, "%s: TCCR4A = %02x\n", machine().describe_context(), data);
- changed_tccr4a(data);
- break;
+ if (changed & TCCR4A_WGM4_10_MASK)
+ {
+ update_timer_waveform_gen_mode(4, WGM4);
+ }
+}
- case AVR8_REGIDX_TCCR4B:
- LOGMASKED(LOG_TIMER4, "%s: TCCR4B = %02x\n", machine().describe_context(), data);
- changed_tccr4b(data);
- break;
+template <int NumTimers>
+void avr8_device<NumTimers>::tccr4b_w(uint8_t data)
+{
+ LOGMASKED(LOG_TIMER4, "%s: TCCR4B = %02x\n", machine().describe_context(), data);
+ const uint8_t oldtccr = m_r[TCCR4B];
+ const uint8_t newtccr = data;
+ const uint8_t changed = newtccr ^ oldtccr;
+ const uint8_t oldcs = (m_r[TCCR4B] & TCCR4B_CS_MASK) >> TCCR4B_CS_SHIFT;
- case AVR8_REGIDX_TCCR4C:
- LOGMASKED(LOG_TIMER4, "%s: TCCR4C = %02x\n", machine().describe_context(), data);
- changed_tccr4c(data);
- break;
+ m_r[TCCR4B] = data;
- case AVR8_REGIDX_TCNT4L:
- AVR8_TCNT4L = data;
- break;
+ if (changed & TCCR4B_FOC4A_MASK)
+ {
+ // TODO
+ // timer4_force_output_compare(AVR8_REG_A);
+ }
- case AVR8_REGIDX_TCNT4H:
- AVR8_TCNT4H = data;
- break;
+ if (changed & TCCR4B_FOC4B_MASK)
+ {
+ // TODO
+ // timer4_force_output_compare(AVR8_REG_B);
+ }
- case AVR8_REGIDX_ICR4L:
- AVR8_ICR4L = data;
- break;
+ if (changed & TCCR4B_WGM4_32_MASK)
+ {
+ update_timer_waveform_gen_mode(4, WGM4);
+ }
- case AVR8_REGIDX_ICR4H:
- AVR8_ICR4H = data;
- break;
+ if (changed & TCCR4B_CS_MASK)
+ {
+ update_timer_clock_source<4>(TIMER4_CLOCK_SELECT, oldcs);
+ }
+}
- case AVR8_REGIDX_OCR4AL:
- AVR8_OCR4AL = data;
- break;
+template <int NumTimers>
+void avr8_device<NumTimers>::tccr4c_w(uint8_t data)
+{
+ LOGMASKED(LOG_TIMER4, "%s: TCCR4C = %02x\n", machine().describe_context(), data);
+ // uint8_t oldtccr = m_r[TCCR4C];
+ // uint8_t newtccr = data;
+ // uint8_t changed = newtccr ^ oldtccr;
- case AVR8_REGIDX_OCR4AH:
- AVR8_OCR4AH = data;
- break;
+ m_r[TCCR4C] = data;
+}
- case AVR8_REGIDX_OCR4BL:
- AVR8_OCR4BL = data;
- break;
+template <int NumTimers>
+void avr8_device<NumTimers>::tcnt4l_w(uint8_t data)
+{
+ m_r[TCNT4L] = data;
+}
- case AVR8_REGIDX_OCR4BH:
- AVR8_OCR4BH = data;
- break;
+template <int NumTimers>
+void avr8_device<NumTimers>::tcnt4h_w(uint8_t data)
+{
+ m_r[TCNT4H] = data;
+}
- case AVR8_REGIDX_OCR4CL:
- AVR8_OCR4CL = data;
- break;
+template <int NumTimers>
+void avr8_device<NumTimers>::icr4l_w(uint8_t data)
+{
+ m_r[ICR4L] = data;
+}
- case AVR8_REGIDX_OCR4CH:
- AVR8_OCR4CH = data;
- break;
+template <int NumTimers>
+void avr8_device<NumTimers>::icr4h_w(uint8_t data)
+{
+ m_r[ICR4H] = data;
+}
- case AVR8_REGIDX_TCCR5A:
- LOGMASKED(LOG_TIMER5, "%s: TCCR5A = %02x\n", machine().describe_context(), data);
- changed_tccr5a(data);
- break;
+template <int NumTimers>
+void avr8_device<NumTimers>::ocr4al_w(uint8_t data)
+{
+ m_r[OCR4AL] = data;
+}
- case AVR8_REGIDX_TCCR5B:
- LOGMASKED(LOG_TIMER5, "%s: TCCR5B = %02x\n", machine().describe_context(), data);
- changed_tccr5b(data);
- break;
+template <int NumTimers>
+void avr8_device<NumTimers>::ocr4ah_w(uint8_t data)
+{
+ m_r[OCR4AH] = data;
+}
- case AVR8_REGIDX_ASSR:
- LOGMASKED(LOG_ASYNC, "%s: (not yet implemented) ASSR = %02x\n", machine().describe_context(), data);
- break;
+template <int NumTimers>
+void avr8_device<NumTimers>::ocr4bl_w(uint8_t data)
+{
+ m_r[OCR4BL] = data;
+}
- case AVR8_REGIDX_TWBR:
- LOGMASKED(LOG_TWI, "%s: (not yet implemented) TWBR = %02x\n", machine().describe_context(), data);
- break;
+template <int NumTimers>
+void avr8_device<NumTimers>::ocr4bh_w(uint8_t data)
+{
+ m_r[OCR4BH] = data;
+}
- case AVR8_REGIDX_TWSR:
- LOGMASKED(LOG_TWI, "%s: (not yet implemented) TWSR = %02x\n", machine().describe_context(), data);
- break;
+template <int NumTimers>
+void avr8_device<NumTimers>::ocr4cl_w(uint8_t data)
+{
+ m_r[OCR4CL] = data;
+}
- case AVR8_REGIDX_TWAR:
- LOGMASKED(LOG_TWI, "%s: (not yet implemented) TWAR = %02x\n", machine().describe_context(), data);
- break;
+template <int NumTimers>
+void avr8_device<NumTimers>::ocr4ch_w(uint8_t data)
+{
+ m_r[OCR4CH] = data;
+}
- case AVR8_REGIDX_TWDR:
- LOGMASKED(LOG_TWI, "%s: (not yet implemented) TWDR = %02x\n", machine().describe_context(), data);
- break;
+template <int NumTimers>
+void avr8_device<NumTimers>::tccr5a_w(uint8_t data)
+{
+ LOGMASKED(LOG_TIMER5, "%s: TCCR5A = %02x\n", machine().describe_context(), data);
+ const uint8_t oldtccr = m_r[TCCR5A];
+ const uint8_t newtccr = data;
+ const uint8_t changed = newtccr ^ oldtccr;
- case AVR8_REGIDX_TWCR:
- LOGMASKED(LOG_TWI, "%s: (not yet implemented) TWCR = %02x\n", machine().describe_context(), data);
- m_r[AVR8_REGIDX_TWCR] = data;
- break;
+ m_r[TCCR5A] = data;
- case AVR8_REGIDX_TWAMR:
- LOGMASKED(LOG_TWI, "%s: (not yet implemented) TWAMR = %02x\n", machine().describe_context(), data);
- break;
+ if (changed & TCCR5A_WGM5_10_MASK)
+ {
+ update_timer_waveform_gen_mode(5, WGM5);
+ }
+}
- case AVR8_REGIDX_UCSR0A:
- LOGMASKED(LOG_UART, "%s: (not yet implemented) UCSR0A = %02x\n", machine().describe_context(), data);
- break;
+template <int NumTimers>
+void avr8_device<NumTimers>::tccr5b_w(uint8_t data)
+{
+ LOGMASKED(LOG_TIMER5, "%s: TCCR5B = %02x\n", machine().describe_context(), data);
+ const uint8_t oldtccr = m_r[TCCR5B];
+ const uint8_t newtccr = data;
+ const uint8_t changed = newtccr ^ oldtccr;
+ const uint8_t oldcs = (m_r[TCCR5B] & TCCR5B_CS_MASK) >> TCCR5B_CS_SHIFT;
- case AVR8_REGIDX_UCSR0B:
- LOGMASKED(LOG_UART, "%s: (not yet implemented) UCSR0B = %02x\n", machine().describe_context(), data);
- break;
+ m_r[TCCR5B] = data;
- case AVR8_REGIDX_UCSR0C:
- LOGMASKED(LOG_UART, "%s: (not yet implemented) UCSR0C = %02x\n", machine().describe_context(), data);
- break;
+ if (changed & TCCR5C_FOC5A_MASK)
+ {
+ // TODO
+ // timer5_force_output_compare(AVR8_REG_A);
+ }
- default:
- LOGMASKED(LOG_UNKNOWN, "%s: Unknown Register Write: %03x = %02x\n", machine().describe_context(), offset, data);
- break;
+ if (changed & TCCR5C_FOC5B_MASK)
+ {
+ // TODO
+ // timer5_force_output_compare(AVR8_REG_B);
}
-}
-uint8_t avr8_device::regs_r(offs_t offset)
-{
- uint8_t data = m_r[offset];
-
- switch (offset)
- {
- case AVR8_REGIDX_R0:
- case AVR8_REGIDX_R1:
- case AVR8_REGIDX_R2:
- case AVR8_REGIDX_R3:
- case AVR8_REGIDX_R4:
- case AVR8_REGIDX_R5:
- case AVR8_REGIDX_R6:
- case AVR8_REGIDX_R7:
- case AVR8_REGIDX_R8:
- case AVR8_REGIDX_R9:
- case AVR8_REGIDX_R10:
- case AVR8_REGIDX_R11:
- case AVR8_REGIDX_R12:
- case AVR8_REGIDX_R13:
- case AVR8_REGIDX_R14:
- case AVR8_REGIDX_R15:
- case AVR8_REGIDX_R16:
- case AVR8_REGIDX_R17:
- case AVR8_REGIDX_R18:
- case AVR8_REGIDX_R19:
- case AVR8_REGIDX_R20:
- case AVR8_REGIDX_R21:
- case AVR8_REGIDX_R22:
- case AVR8_REGIDX_R23:
- case AVR8_REGIDX_R24:
- case AVR8_REGIDX_R25:
- case AVR8_REGIDX_R26:
- case AVR8_REGIDX_R27:
- case AVR8_REGIDX_R28:
- case AVR8_REGIDX_R29:
- case AVR8_REGIDX_R30:
- case AVR8_REGIDX_R31:
- return data;
-
- case AVR8_REGIDX_PINA:
- // TODO: account for DDRA
- return m_io->read_byte(AVR8_REG_A);
-
- case AVR8_REGIDX_PINB:
- // TODO: account for DDRB
- return m_io->read_byte(AVR8_REG_B);
-
- case AVR8_REGIDX_PINC:
- // TODO: account for DDRC
- return m_io->read_byte(AVR8_REG_C);
-
- case AVR8_REGIDX_PIND:
- // TODO: account for DDRD
- return m_io->read_byte(AVR8_REG_D);
-
- case AVR8_REGIDX_PINE:
- // TODO: account for DDRE
- return m_io->read_byte(AVR8_REG_E);
-
- case AVR8_REGIDX_PINF:
- // TODO: account for DDRF
- return m_io->read_byte(AVR8_REG_F);
-
- case AVR8_REGIDX_PING:
- // TODO: account for DDRG
- return m_io->read_byte(AVR8_REG_G);
-
- case AVR8_REGIDX_PINH:
- // TODO: account for DDRH
- return m_io->read_byte(AVR8_REG_H);
-
- case AVR8_REGIDX_PINJ:
- // TODO: account for DDRJ
- return m_io->read_byte(AVR8_REG_J);
-
- case AVR8_REGIDX_PINK:
- // TODO: account for DDRK
- return m_io->read_byte(AVR8_REG_K);
-
- case AVR8_REGIDX_PINL:
- // TODO: account for DDRL
- return m_io->read_byte(AVR8_REG_L);
-
- case AVR8_REGIDX_PORTA:
- case AVR8_REGIDX_PORTB:
- case AVR8_REGIDX_PORTC:
- case AVR8_REGIDX_PORTD:
- case AVR8_REGIDX_PORTE:
- case AVR8_REGIDX_PORTF:
- case AVR8_REGIDX_PORTG:
- case AVR8_REGIDX_PORTH:
- case AVR8_REGIDX_PORTJ:
- case AVR8_REGIDX_PORTK:
- case AVR8_REGIDX_PORTL:
- return data;
-
- case AVR8_REGIDX_DDRA:
- case AVR8_REGIDX_DDRB:
- case AVR8_REGIDX_DDRC:
- case AVR8_REGIDX_DDRD:
- case AVR8_REGIDX_DDRE:
- case AVR8_REGIDX_DDRF:
- case AVR8_REGIDX_DDRG:
- case AVR8_REGIDX_DDRH:
- case AVR8_REGIDX_DDRJ:
- case AVR8_REGIDX_DDRK:
- case AVR8_REGIDX_DDRL:
- return data;
-
- // EEPROM registers
- case AVR8_REGIDX_EECR:
- case AVR8_REGIDX_EEDR:
- return data;
-
- // Miscellaneous registers
- // TODO: Implement readback for all applicable registers.
-
- case AVR8_REGIDX_GPIOR0:
- LOGMASKED(LOG_GPIO, "%s: GPIOR0 Read: %02x\n", machine().describe_context(), data);
- return data;
- case AVR8_REGIDX_GPIOR1:
- LOGMASKED(LOG_GPIO, "%s: GPIOR1 Read: %02x\n", machine().describe_context(), data);
- return data;
- case AVR8_REGIDX_GPIOR2:
- LOGMASKED(LOG_GPIO, "%s: GPIOR2 Read: %02x\n", machine().describe_context(), data);
- return data;
-// case AVR8_REGIDX_UCSR0B: // TODO: needed for Replicator 1
- case AVR8_REGIDX_SPDR: // TODO: needed for Replicator 1
- case AVR8_REGIDX_SPSR: // TODO: needed for Replicator 1
-// case AVR8_REGIDX_ADCSRA: // TODO: needed for Replicator 1
-// case AVR8_REGIDX_ADCSRB: // TODO: needed for Replicator 1
- case AVR8_REGIDX_SPL:
- case AVR8_REGIDX_SPH:
- case AVR8_REGIDX_SREG:
- case AVR8_REGIDX_TIMSK0:
- LOGMASKED(LOG_TIMER0, "%s: TIMSK0 Read: %02x\n", machine().describe_context(), data);
- return data;
- case AVR8_REGIDX_TIMSK1:
- LOGMASKED(LOG_TIMER1, "%s: TIMSK1 Read: %02x\n", machine().describe_context(), data);
- return data;
- case AVR8_REGIDX_TIMSK2:
- LOGMASKED(LOG_TIMER2, "%s: TIMSK2 Read: %02x\n", machine().describe_context(), data);
- return data;
- case AVR8_REGIDX_TIMSK3:
- LOGMASKED(LOG_TIMER3, "%s: TIMSK3 Read: %02x\n", machine().describe_context(), data);
- return data;
- case AVR8_REGIDX_TIMSK4:
- LOGMASKED(LOG_TIMER4, "%s: TIMSK4 Read: %02x\n", machine().describe_context(), data);
- return data;
- case AVR8_REGIDX_TIMSK5:
- LOGMASKED(LOG_TIMER5, "%s: TIMSK5 Read: %02x\n", machine().describe_context(), data);
- return data;
- case AVR8_REGIDX_TIFR1:
- //LOGMASKED(LOG_TIMER0, "%s: TIFR1 Read: %02x\n", machine().describe_context(), data);
- return data;
-
- // Two-wire registers
- case AVR8_REGIDX_TWCR:
- // TODO: needed for Replicator 1
- return m_r[offset];
-
- case AVR8_REGIDX_TWSR:
- // HACK for Replicator 1:
- // By returning a value != 0x08, we induce an error state that makes the object code jump out of the wait loop,
- // and continue execution failing the 2-wire write operation.
- return 0x00;
-
-
- case AVR8_REGIDX_TCNT1L:
- return (uint8_t)m_timer1_count;
- case AVR8_REGIDX_TCNT1H:
- return (uint8_t)(m_timer1_count >> 8);
- case AVR8_REGIDX_TCNT2:
- case AVR8_REGIDX_UCSR0A:
- return m_r[offset];
+ if (changed & TCCR5C_FOC5C_MASK)
+ {
+ // TODO
+ // timer5_force_output_compare(AVR8_REG_C);
+ }
- default:
- LOGMASKED(LOG_UNKNOWN, "%s: Unknown Register Read: %03X\n", machine().describe_context(), offset);
- return 0;
+ if (changed & TCCR5B_WGM5_32_MASK)
+ {
+ update_timer_waveform_gen_mode(5, WGM5);
}
-}
+ if (changed & TCCR5B_CS_MASK)
+ {
+ update_timer_clock_source<5>(TIMER5_CLOCK_SELECT, oldcs);
+ }
+}
-//**************************************************************************
-// CORE EXECUTION LOOP
-//**************************************************************************
+template <int NumTimers>
+void avr8_device<NumTimers>::assr_w(uint8_t data)
+{
+ LOGMASKED(LOG_ASYNC, "%s: (not yet implemented) ASSR = %02x\n", machine().describe_context(), data);
+}
-//-------------------------------------------------
-// execute_min_cycles - return minimum number of
-// cycles it takes for one instruction to execute
-//-------------------------------------------------
+template <int NumTimers>
+void avr8_device<NumTimers>::twbr_w(uint8_t data)
+{
+ LOGMASKED(LOG_TWI, "%s: (not yet implemented) TWBR = %02x\n", machine().describe_context(), data);
+}
-uint32_t avr8_device::execute_min_cycles() const noexcept
+template <int NumTimers>
+uint8_t avr8_device<NumTimers>::twsr_r()
{
- return 1;
+ LOGMASKED(LOG_TWI, "%s: (not yet implemented) Read TWSR: %02x\n", machine().describe_context(), 0);
+ // HACK for Replicator 1:
+ // By returning a value != 0x08, we induce an error state that makes the object code jump out of the wait loop,
+ // and continue execution failing the 2-wire write operation.
+ return 0x00;
}
+template <int NumTimers>
+void avr8_device<NumTimers>::twsr_w(uint8_t data)
+{
+ LOGMASKED(LOG_TWI, "%s: (not yet implemented) TWSR = %02x\n", machine().describe_context(), data);
+}
-//-------------------------------------------------
-// execute_max_cycles - return maximum number of
-// cycles it takes for one instruction to execute
-//-------------------------------------------------
+template <int NumTimers>
+void avr8_device<NumTimers>::twar_w(uint8_t data)
+{
+ LOGMASKED(LOG_TWI, "%s: (not yet implemented) TWAR = %02x\n", machine().describe_context(), data);
+}
-uint32_t avr8_device::execute_max_cycles() const noexcept
+template <int NumTimers>
+void avr8_device<NumTimers>::twdr_w(uint8_t data)
{
- return 4;
+ LOGMASKED(LOG_TWI, "%s: (not yet implemented) TWDR = %02x\n", machine().describe_context(), data);
}
+template <int NumTimers>
+void avr8_device<NumTimers>::twcr_w(uint8_t data)
+{
+ LOGMASKED(LOG_TWI, "%s: (not yet implemented) TWCR = %02x\n", machine().describe_context(), data);
+ m_r[TWCR] = data;
+}
-//-------------------------------------------------
-// execute_input_lines - return the number of
-// input/interrupt lines
-//-------------------------------------------------
+template <int NumTimers>
+void avr8_device<NumTimers>::twamr_w(uint8_t data)
+{
+ LOGMASKED(LOG_TWI, "%s: (not yet implemented) TWAMR = %02x\n", machine().describe_context(), data);
+}
-uint32_t avr8_device::execute_input_lines() const noexcept
+template <int NumTimers>
+void avr8_device<NumTimers>::ucsr0a_w(uint8_t data)
{
- return 0;
+ LOGMASKED(LOG_UART, "%s: (not yet implemented) UCSR0A = %02x\n", machine().describe_context(), data);
}
+template <int NumTimers>
+void avr8_device<NumTimers>::ucsr0b_w(uint8_t data)
+{
+ LOGMASKED(LOG_UART, "%s: (not yet implemented) UCSR0B = %02x\n", machine().describe_context(), data);
+}
-void avr8_device::execute_set_input(int inputnum, int state)
+template <int NumTimers>
+void avr8_device<NumTimers>::ucsr0c_w(uint8_t data)
{
+ LOGMASKED(LOG_UART, "%s: (not yet implemented) UCSR0C = %02x\n", machine().describe_context(), data);
}
+
+//**************************************************************************
+// CORE EXECUTION LOOP
+//**************************************************************************
+
#include "avr8ops.hxx"
//-------------------------------------------------
@@ -3184,24 +3449,75 @@ void avr8_device::execute_set_input(int inputnum, int state)
// opcodes
//-------------------------------------------------
-void avr8_device::execute_run()
+template <int NumTimers>
+void avr8_device<NumTimers>::execute_run()
{
while (m_icount > 0)
{
m_pc &= m_addr_mask;
- m_shifted_pc &= (m_addr_mask << 1) | 1;
-
- debugger_instruction_hook(m_shifted_pc);
+ debugger_instruction_hook(m_pc);
- const uint16_t op = (uint32_t)m_program->read_word(m_shifted_pc);
+ const uint16_t op = (uint32_t)m_program->read_word(m_pc);
m_opcycles = m_op_cycles[op];
((this)->*(m_op_funcs[op]))(op);
- m_pc++;
-
- m_shifted_pc = m_pc << 1;
+ m_pc += 2;
m_icount -= m_opcycles;
- timer_tick();
+ for (int i = 0; i < m_opcycles; i++)
+ {
+ if (m_spi_active && m_spi_prescale > 0)
+ {
+ if (m_spi_prescale_countdown >= 0)
+ {
+ m_spi_prescale_count++;
+ if (m_spi_prescale_count >= m_spi_prescale)
+ {
+ spi_tick();
+ m_spi_prescale_count -= m_spi_prescale;
+ }
+ }
+ }
+
+ m_timer_prescale_count[0]++;
+ if (m_timer_prescale_count[0] > m_timer_prescale[0])
+ m_timer0_tick();
+
+ m_timer_prescale_count[1]++;
+ if (m_timer_prescale_count[1] > m_timer_prescale[1])
+ m_timer1_tick();
+
+ m_timer_prescale_count[2]++;
+ if (m_timer_prescale_count[2] > m_timer_prescale[2])
+ m_timer2_tick();
+
+ if (NumTimers > 5)
+ {
+ m_timer_prescale_count[3]++;
+ if (m_timer_prescale_count[3] > m_timer_prescale[3])
+ {
+ timer3_tick();
+ m_timer_prescale_count[3] -= m_timer_prescale[3];
+ }
+
+ m_timer_prescale_count[4]++;
+ if (m_timer_prescale_count[4] > m_timer_prescale[4])
+ {
+ timer4_tick();
+ m_timer_prescale_count[4] -= m_timer_prescale[4];
+ }
+
+ m_timer_prescale_count[5]++;
+ if (m_timer_prescale_count[5] > m_timer_prescale[5])
+ {
+ timer5_tick();
+ m_timer_prescale_count[5] -= m_timer_prescale[5];
+ }
+ }
+ }
}
}
+
+template class avr8_device<2>;
+template class avr8_device<3>;
+template class avr8_device<6>;