01234567890123456789012345678901234567890123456789012345678901234567890123456789

-avr8: Implemented MULS, ANDI, STD Z+, LD -Z, LD Y+, LD -Y, LD -X, SWAP, ASR,
 ROR, and SBIS opcodes. [MooglyGuy]

-avr8: Moved Timer 0-2 into the CPU core itself, 30x driver speedup [MooglyGuy]

-cratft.c: Fixed DAC bit order, audio now plays but is 40% too slow [Mooglyguy]
This commit is contained in:
Ryan Holtz 2012-10-25 04:01:46 +00:00
parent 9dfaad4477
commit 4212614f83
6 changed files with 1481 additions and 1209 deletions

1
.gitattributes vendored
View File

@ -6554,7 +6554,6 @@ src/mess/machine/at_keybc.h svneol=native#text/plain
src/mess/machine/ataricrt.c svneol=native#text/plain
src/mess/machine/ataridev.h svneol=native#text/plain
src/mess/machine/atarifdc.c svneol=native#text/plain
src/mess/machine/avr8.h svneol=native#text/plain
src/mess/machine/ay31015.c svneol=native#text/plain
src/mess/machine/ay31015.h svneol=native#text/plain
src/mess/machine/ay3600.c svneol=native#text/plain

File diff suppressed because it is too large Load Diff

View File

@ -11,6 +11,39 @@
#ifndef __AVR8_H__
#define __AVR8_H__
// Used by core CPU interface
struct avr8_state
{
UINT32 pc;
legacy_cpu_device *device;
address_space *program;
address_space *io;
int icount;
UINT32 addr_mask;
UINT8 r[256];
UINT8 status;
UINT8 timer0_top;
INT32 timer0_increment;
UINT16 timer0_prescale;
UINT16 timer0_prescale_count;
UINT16 timer1_top;
INT32 timer1_increment;
UINT16 timer1_prescale;
UINT16 timer1_prescale_count;
UINT8 timer2_top;
INT32 timer2_increment;
UINT16 timer2_prescale;
UINT16 timer2_prescale_count;
bool interrupt_pending;
};
enum
{
AVR8_SREG = 1,
@ -83,9 +116,192 @@ enum
AVR8_INT_SPM_RDY,
};
// Used by I/O register handling
enum
{
AVR8_REGIDX_R0 = 0,
AVR8_REGIDX_R1,
AVR8_REGIDX_R2,
AVR8_REGIDX_R3,
AVR8_REGIDX_R4,
AVR8_REGIDX_R5,
AVR8_REGIDX_R6,
AVR8_REGIDX_R7,
AVR8_REGIDX_R8,
AVR8_REGIDX_R9,
AVR8_REGIDX_R10,
AVR8_REGIDX_R11,
AVR8_REGIDX_R12,
AVR8_REGIDX_R13,
AVR8_REGIDX_R14,
AVR8_REGIDX_R15,
AVR8_REGIDX_R16,
AVR8_REGIDX_R17,
AVR8_REGIDX_R18,
AVR8_REGIDX_R19,
AVR8_REGIDX_R20,
AVR8_REGIDX_R21,
AVR8_REGIDX_R22,
AVR8_REGIDX_R23,
AVR8_REGIDX_R24,
AVR8_REGIDX_R25,
AVR8_REGIDX_R26,
AVR8_REGIDX_R27,
AVR8_REGIDX_R28,
AVR8_REGIDX_R29,
AVR8_REGIDX_R30,
AVR8_REGIDX_R31,
AVR8_REGIDX_PINB = 0x23,
AVR8_REGIDX_DDRB,
AVR8_REGIDX_PORTB,
AVR8_REGIDX_PINC,
AVR8_REGIDX_DDRC,
AVR8_REGIDX_PORTC,
AVR8_REGIDX_PIND,
AVR8_REGIDX_DDRD,
AVR8_REGIDX_PORTD,
AVR8_REGIDX_TIFR0 = 0x35,
AVR8_REGIDX_TIFR1,
AVR8_REGIDX_TIFR2,
AVR8_REGIDX_PCIFR = 0x3b,
AVR8_REGIDX_EIFR,
AVR8_REGIDX_EIMSK,
AVR8_REGIDX_GPIOR0,
AVR8_REGIDX_EECR,
AVR8_REGIDX_EEDR,
AVR8_REGIDX_EEARL,
AVR8_REGIDX_EEARH,
AVR8_REGIDX_GTCCR,
AVR8_REGIDX_TCCR0A,
AVR8_REGIDX_TCCR0B,
AVR8_REGIDX_TCNT0,
AVR8_REGIDX_OCR0A,
AVR8_REGIDX_OCR0B,
AVR8_REGIDX_GPIOR1 = 0x4a,
AVR8_REGIDX_GPIOR2,
AVR8_REGIDX_SPCR,
AVR8_REGIDX_SPSR,
AVR8_REGIDX_SPDR,
AVR8_REGIDX_ACSR = 0x50,
AVR8_REGIDX_SMCR = 0x53,
AVR8_REGIDX_MCUSR,
AVR8_REGIDX_MCUCR,
AVR8_REGIDX_SPMCSR = 0x57,
AVR8_REGIDX_SPL = 0x5d,
AVR8_REGIDX_SPH,
AVR8_REGIDX_SREG,
AVR8_REGIDX_WDTCSR,
AVR8_REGIDX_CLKPR,
AVR8_REGIDX_PRR = 0x64,
AVR8_REGIDX_OSCCAL = 0x66,
AVR8_REGIDX_PCICR = 0x68,
AVR8_REGIDX_EICRA,
AVR8_REGIDX_PCMSK0 = 0x6B,
AVR8_REGIDX_PCMSK1,
AVR8_REGIDX_PCMSK2,
AVR8_REGIDX_TIMSK0,
AVR8_REGIDX_TIMSK1,
AVR8_REGIDX_TIMSK2,
AVR8_REGIDX_ADCL = 0x78,
AVR8_REGIDX_ADCH,
AVR8_REGIDX_ADCSRA,
AVR8_REGIDX_ADCSRB,
AVR8_REGIDX_ADMUX,
AVR8_REGIDX_DIDR0 = 0x7e,
AVR8_REGIDX_DIDR1,
AVR8_REGIDX_TCCR1A,
AVR8_REGIDX_TCCR1B,
AVR8_REGIDX_TCCR1C,
AVR8_REGIDX_TCNT1L = 0x84,
AVR8_REGIDX_TCNT1H,
AVR8_REGIDX_ICR1L,
AVR8_REGIDX_ICR1H,
AVR8_REGIDX_OCR1AL,
AVR8_REGIDX_OCR1AH,
AVR8_REGIDX_OCR1BL,
AVR8_REGIDX_OCR1BH,
AVR8_REGIDX_TCCR2A = 0xb0,
AVR8_REGIDX_TCCR2B,
AVR8_REGIDX_TCNT2,
AVR8_REGIDX_OCR2A,
AVR8_REGIDX_OCR2B,
AVR8_REGIDX_ASSR = 0xb6,
AVR8_REGIDX_TWBR = 0xb8,
AVR8_REGIDX_TWSR,
AVR8_REGIDX_TWAR,
AVR8_REGIDX_TWDR,
AVR8_REGIDX_TWCR,
AVR8_REGIDX_TWAMR,
AVR8_REGIDX_UCSR0A = 0xc0,
AVR8_REGIDX_UCSR0B,
AVR8_REGIDX_UCSR0C,
AVR8_REGIDX_UBRR0L = 0xc4,
AVR8_REGIDX_UBRR0H,
AVR8_REGIDX_UDR0
};
enum
{
AVR8_REG_A = 0,
AVR8_REG_B,
AVR8_REG_C,
AVR8_REG_D,
};
enum
{
AVR8_INTIDX_SPI,
AVR8_INTIDX_ICF1,
AVR8_INTIDX_OCF1B,
AVR8_INTIDX_OCF1A,
AVR8_INTIDX_TOV1,
AVR8_INTIDX_OCF2B,
AVR8_INTIDX_OCF2A,
AVR8_INTIDX_TOV2,
AVR8_INTIDX_COUNT,
};
#define AVR8_EECR_EERE 0x01
#define AVR8_EEARH_MASK 0x01
#define AVR8_SPSR_SPIF_MASK 0x80
#define AVR8_SPSR_SPIF_SHIFT 7
#define AVR8_SPSR_SPR2X_MASK 0x01
#define AVR8_SPCR_SPIE_MASK 0x80
#define AVR8_SPCR_SPE_MASK 0x40
#define AVR8_SPCR_DORD_MASK 0x20
#define AVR8_SPCR_MSTR_MASK 0x10
#define AVR8_SPCR_CPOL_MASK 0x08
#define AVR8_SPCR_CPHA_MASK 0x04
#define AVR8_SPCR_SPR_MASK 0x03
DECLARE_LEGACY_CPU_DEVICE(ATMEGA88, atmega88);
DECLARE_LEGACY_CPU_DEVICE(ATMEGA644, atmega644);
void avr8_update_interrupt(device_t *device, int source);
CPU_DISASSEMBLE( avr8 );
#endif /* __AVR8_H__ */

View File

@ -6,7 +6,6 @@
#include "emu.h"
#include "cpu/avr8/avr8.h"
#include "machine/avr8.h"
#include "sound/dac.h"
#define VERBOSE_LEVEL (99)
@ -33,12 +32,30 @@ INLINE void verboselog(running_machine &machine, int n_level, const char *s_fmt,
#define MASTER_CLOCK 20000000
/****************************************************\
* I/O devices *
* I/O defines *
\****************************************************/
#define AVR8_DDRD (state->m_regs[AVR8_REGIDX_DDRD])
#define AVR8_DDRC (state->m_regs[AVR8_REGIDX_DDRC])
#define AVR8_PORTB (state->m_regs[AVR8_REGIDX_PORTB])
#define AVR8_DDRB (state->m_regs[AVR8_REGIDX_DDRB])
#define AVR8_SPSR (state->m_regs[AVR8_REGIDX_SPSR])
#define AVR8_SPSR_SPR2X (AVR8_SPSR & AVR8_SPSR_SPR2X_MASK)
#define AVR8_SPCR (state->m_regs[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)
/****************************************************\
* I/O devices *
\****************************************************/
class craft_state : public driver_device
{
@ -47,11 +64,6 @@ public:
: driver_device(mconfig, type, tag),
m_maincpu(*this, "maincpu")
{
m_timer0_increment = 1;
m_timer1_increment = 1;
m_timer2_increment = 1;
}
virtual void machine_start();
@ -59,20 +71,10 @@ public:
dac_device* dac;
UINT8 m_regs[0x100];
UINT8* m_eeprom;
required_device<cpu_device> m_maincpu;
emu_timer* m_timer0_timer;
UINT8 m_timer0_top;
INT32 m_timer0_increment;
emu_timer* m_timer1_timer;
UINT16 m_timer1_top;
INT32 m_timer1_increment;
emu_timer* m_timer2_timer;
UINT8 m_timer2_top;
INT32 m_timer2_increment;
DECLARE_READ8_MEMBER(avr8_read);
DECLARE_WRITE8_MEMBER(avr8_write);
DECLARE_DRIVER_INIT(craft);
@ -85,113 +87,13 @@ public:
void craft_state::machine_start()
{
m_timer0_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(craft_state::avr8_timer0_tick),this));
m_timer1_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(craft_state::avr8_timer1_tick),this));
m_timer2_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(craft_state::avr8_timer2_tick),this));
}
enum
{
AVR8_REG_A = 0,
AVR8_REG_B,
AVR8_REG_C,
AVR8_REG_D,
};
static const char avr8_reg_name[4] = { 'A', 'B', 'C', 'D' };
TIMER_CALLBACK_MEMBER(craft_state::avr8_timer0_tick)
{
// TODO
}
TIMER_CALLBACK_MEMBER(craft_state::avr8_timer1_tick)
{
/* TODO: Handle comparison, setting OC1x pins, detection of BOTTOM and TOP */
UINT16 count = (m_regs[Avr8::REGIDX_TCNT1H] << 8) | m_regs[Avr8::REGIDX_TCNT1L];
INT32 wgm1 = ((m_regs[Avr8::REGIDX_TCCR1B] & AVR8_TCCR1B_WGM1_32_MASK) >> 1) |
(m_regs[Avr8::REGIDX_TCCR1A] & AVR8_TCCR1A_WGM1_10_MASK);
// Cache things in array form to avoid a compare+branch inside a potentially high-frequency timer
//UINT8 compare_mode[2] = { (m_regs[Avr8::REGIDX_TCCR1A] & AVR8_TCCR1A_COM1A_MASK) >> AVR8_TCCR1A_COM1A_SHIFT,
//(m_regs[Avr8::REGIDX_TCCR1A] & AVR8_TCCR1A_COM1B_MASK) >> AVR8_TCCR1A_COM1B_SHIFT };
UINT16 ocr1[2] = { (m_regs[Avr8::REGIDX_OCR1AH] << 8) | m_regs[Avr8::REGIDX_OCR1AL],
(m_regs[Avr8::REGIDX_OCR1BH] << 8) | m_regs[Avr8::REGIDX_OCR1BL] };
INT32 int_lines[2] = { AVR8_INT_T1COMPA, AVR8_INT_T1COMPB };
INT32 int_masks[2] = { AVR8_TIMSK1_OCIE1A_MASK, AVR8_TIMSK1_OCIE1B_MASK };
INT32 increment = m_timer1_increment;
for(INT32 reg = AVR8_REG_A; reg <= AVR8_REG_B; reg++)
{
switch(wgm1)
{
case Avr8::WGM1_FAST_PWM_OCR:
if(count == ocr1[reg])
{
if (reg == 0)
{
m_regs[Avr8::REGIDX_TIFR1] |= (1 << AVR8_TIFR1_TOV1_SHIFT);
count = 0;
increment = 0;
}
if (m_regs[Avr8::REGIDX_TIMSK1] & int_masks[reg])
{
m_maincpu->set_input_line(int_lines[reg], 1);
}
}
else if(count == 0)
{
if (reg == 0)
{
m_regs[Avr8::REGIDX_TIFR1] &= ~AVR8_TIFR1_TOV1_MASK;
}
if (m_regs[Avr8::REGIDX_TIMSK1] & int_masks[reg])
{
m_maincpu->set_input_line(int_lines[reg], 0);
}
}
break;
default:
// TODO
break;
}
/*
switch(compare_mode[reg])
{
case 0:
//verboselog(machine(), 0, "avr8_update_timer1_compare_mode: Normal port operation (OC1 disconnected)\n");
break;
case 1:
case 2:
// TODO
break;
case 3:
break;
}
*/
}
count += increment;
m_regs[Avr8::REGIDX_TCNT1H] = (count >> 8) & 0xff;
m_regs[Avr8::REGIDX_TCNT1L] = count & 0xff;
}
READ8_MEMBER(craft_state::avr8_read)
{
if(offset <= Avr8::REGIDX_R31)
{
return m_regs[offset];
}
switch( offset )
{
case Avr8::REGIDX_SPL:
case Avr8::REGIDX_SPH:
case Avr8::REGIDX_SREG:
case AVR8_REGIDX_EEDR:
return m_regs[offset];
default:
@ -252,51 +154,13 @@ static void avr8_change_port(running_machine &machine, int reg, UINT8 data)
{
// TODO
//verboselog(machine, 0, "avr8_change_port: PORT%c lines %02x changed\n", avr8_reg_name[reg], changed);
if (reg == AVR8_REG_D) {
state->dac->write_unsigned8(data & 0x7f);
}
}
}
namespace Avr8
{
if (reg == AVR8_REG_D) {
UINT8 audio_sample = (data & 0x02) | ((data & 0xf4) >> 2);
enum
{
INTIDX_SPI,
INTIDX_ICF1,
INTIDX_OCF1B,
INTIDX_OCF1A,
INTIDX_TOV1,
INTIDX_COUNT,
};
class CInterruptCondition
{
public:
UINT8 m_intindex;
UINT8 m_regindex;
UINT8 m_regmask;
UINT8 m_regshift;
UINT8* mp_reg;
};
static const CInterruptCondition s_int_conditions[INTIDX_COUNT] =
{
{ INTIDX_SPI, REGIDX_SPSR, AVR8_SPSR_SPIF_MASK, AVR8_SPSR_SPIF_SHIFT, NULL },
{ INTIDX_ICF1, REGIDX_TIFR1, AVR8_TIFR1_ICF1_MASK, AVR8_TIFR1_ICF1_SHIFT, NULL },
{ INTIDX_OCF1B, REGIDX_TIFR1, AVR8_TIFR1_OCF1B_MASK, AVR8_TIFR1_OCF1B_SHIFT, NULL },
{ INTIDX_OCF1A, REGIDX_TIFR1, AVR8_TIFR1_OCF1A_MASK, AVR8_TIFR1_OCF1A_SHIFT, NULL },
{ INTIDX_TOV1, REGIDX_TIFR1, AVR8_TIFR1_TOV1_MASK, AVR8_TIFR1_TOV1_SHIFT, NULL }
};
}
static void avr8_interrupt_update(running_machine &machine, int source)
{
// TODO
verboselog(machine, 0, "avr8_interrupt_update: TODO; source interrupt is %d\n", source);
state->dac->write_unsigned8(audio_sample << 2);
}
}
/****************/
@ -319,21 +183,21 @@ static void avr8_spi_update_masterslave_select(running_machine &machine)
{
// TODO
//craft_state *state = machine.driver_data<craft_state>();
verboselog(machine, 0, "avr8_spi_update_masterslave_select: TODO; AVR is %s\n", AVR8_SPCR_MSTR ? "Master" : "Slave");
//verboselog(machine, 0, "avr8_spi_update_masterslave_select: TODO; AVR is %s\n", AVR8_SPCR_MSTR ? "Master" : "Slave");
}
static void avr8_spi_update_clock_polarity(running_machine &machine)
{
// TODO
//craft_state *state = machine.driver_data<craft_state>();
verboselog(machine, 0, "avr8_spi_update_clock_polarity: TODO; SCK is Active-%s\n", AVR8_SPCR_CPOL ? "Low" : "High");
//verboselog(machine, 0, "avr8_spi_update_clock_polarity: TODO; SCK is Active-%s\n", AVR8_SPCR_CPOL ? "Low" : "High");
}
static void avr8_spi_update_clock_phase(running_machine &machine)
{
// TODO
//craft_state *state = machine.driver_data<craft_state>();
verboselog(machine, 0, "avr8_spi_update_clock_phase: TODO; Sampling edge is %s\n", AVR8_SPCR_CPHA ? "Trailing" : "Leading");
//verboselog(machine, 0, "avr8_spi_update_clock_phase: TODO; Sampling edge is %s\n", AVR8_SPCR_CPHA ? "Trailing" : "Leading");
}
static const UINT8 avr8_spi_clock_divisor[8] = { 4, 16, 64, 128, 2, 8, 32, 64 };
@ -342,7 +206,7 @@ static void avr8_spi_update_clock_rate(running_machine &machine)
{
// TODO
//craft_state *state = machine.driver_data<craft_state>();
verboselog(machine, 0, "avr8_spi_update_clock_rate: TODO; New clock rate should be f/%d\n", avr8_spi_clock_divisor[AVR8_SPCR_SPR] / (AVR8_SPSR_SPR2X ? 2 : 1));
//verboselog(machine, 0, "avr8_spi_update_clock_rate: TODO; New clock rate should be f/%d\n", avr8_spi_clock_divisor[AVR8_SPCR_SPR] / (AVR8_SPSR_SPR2X ? 2 : 1));
}
static void avr8_change_spcr(running_machine &machine, UINT8 data)
@ -360,7 +224,7 @@ static void avr8_change_spcr(running_machine &machine, UINT8 data)
if(changed & AVR8_SPCR_SPIE_MASK)
{
// Check for SPI interrupt condition
avr8_interrupt_update(machine, Avr8::INTIDX_SPI);
avr8_update_interrupt(state->m_maincpu, AVR8_INTIDX_SPI);
}
if(low_to_high & AVR8_SPCR_SPE_MASK)
@ -412,510 +276,57 @@ static void avr8_change_spsr(running_machine &machine, UINT8 data)
}
}
/********************/
/* Timer 1 Handling */
/********************/
static void avr8_change_timsk1(running_machine &machine, UINT8 data)
{
craft_state *state = machine.driver_data<craft_state>();
UINT8 oldtimsk = AVR8_TIMSK1;
UINT8 newtimsk = data;
UINT8 changed = newtimsk ^ oldtimsk;
AVR8_TIMSK1 = newtimsk;
if(changed & AVR8_TIMSK1_ICIE1_MASK)
{
// Check for Input Capture Interrupt interrupt condition
avr8_interrupt_update(machine, Avr8::INTIDX_ICF1);
}
if(changed & AVR8_TIMSK1_OCIE1B_MASK)
{
// Check for Output Compare B Interrupt interrupt condition
avr8_interrupt_update(machine, Avr8::INTIDX_OCF1B);
}
if(changed & AVR8_TIMSK1_OCIE1A_MASK)
{
// Check for Output Compare A Interrupt interrupt condition
avr8_interrupt_update(machine, Avr8::INTIDX_OCF1A);
}
if(changed & AVR8_TIMSK1_TOIE1_MASK)
{
// Check for Output Compare A Interrupt interrupt condition
avr8_interrupt_update(machine, Avr8::INTIDX_TOV1);
}
}
static void avr8_update_timer1_waveform_gen_mode(running_machine &machine)
{
// TODO
craft_state *state = machine.driver_data<craft_state>();
state->m_timer1_top = 0;
verboselog(machine, 0, "avr8_update_timer1_waveform_gen_mode: TODO; WGM1 is %d\n", AVR8_WGM1 );
switch(AVR8_WGM1)
{
case Avr8::WGM1_NORMAL:
state->m_timer1_top = 0xffff;
break;
case Avr8::WGM1_PWM_8_PC:
case Avr8::WGM1_FAST_PWM_8:
state->m_timer1_top = 0x00ff;
break;
case Avr8::WGM1_PWM_9_PC:
case Avr8::WGM1_FAST_PWM_9:
state->m_timer1_top = 0x01ff;
break;
case Avr8::WGM1_PWM_10_PC:
case Avr8::WGM1_FAST_PWM_10:
state->m_timer1_top = 0x03ff;
break;
case Avr8::WGM1_PWM_PFC_ICR:
case Avr8::WGM1_PWM_PC_ICR:
case Avr8::WGM1_CTC_ICR:
case Avr8::WGM1_FAST_PWM_ICR:
state->m_timer1_top = AVR8_ICR1;
break;
case Avr8::WGM1_PWM_PFC_OCR:
case Avr8::WGM1_PWM_PC_OCR:
case Avr8::WGM1_CTC_OCR:
case Avr8::WGM1_FAST_PWM_OCR:
state->m_timer1_top = AVR8_OCR1A;
break;
default:
verboselog(machine, 0, "avr8_update_timer1_waveform_gen_mode: Unsupported waveform generation type: %d\n", AVR8_WGM1);
break;
}
}
static void avr8_changed_tccr1a(running_machine &machine, UINT8 data)
{
craft_state *state = machine.driver_data<craft_state>();
UINT8 oldtccr = AVR8_TCCR1A;
UINT8 newtccr = data;
UINT8 changed = newtccr ^ oldtccr;
state->m_regs[Avr8::REGIDX_TCCR1A] = newtccr;
if(changed & AVR8_TCCR1A_WGM1_10_MASK)
{
// TODO
avr8_update_timer1_waveform_gen_mode(machine);
}
}
static void avr8_update_timer1_input_noise_canceler(running_machine &machine)
{
}
static void avr8_update_timer1_input_edge_select(running_machine &machine)
{
// TODO
//craft_state *state = machine.driver_data<craft_state>();
verboselog(machine, 0, "avr8_update_timer1_input_edge_select: TODO; Clocking edge is %s\n", "test");
}
TIMER_CALLBACK_MEMBER(craft_state::avr8_timer2_tick)
{
/* TODO: Handle comparison, setting OC2x pins, detection of BOTTOM and TOP
UINT16 count = AVR8_TCNT2;
count += m_timer1_increment;
for(INT32 reg = AVR8_REG_A; reg <= AVR8_REG_B; reg++)
{
UINT8 mode = (reg == AVR8_REG_A) ? AVR8_TCCR2A_COM2A : AVR8_TCCR2A_COM2B;
if(!mode)
{
// Normal port operation, OC2n disconnected
//verboselog(machine(), 0, "avr8_update_timer2_compare_mode: TODO; OC2%c disconnected, normal port operation\n", avr8_reg_name[reg]);
return;
}
switch(AVR8_WGM2)
{
case Avr8::WGM2_NORMAL:
case Avr8::WGM2_CTC_CMP:
switch(mode)
{
case 1: // Toggle OC2n on Compare Match
//verboselog(machine(), 0, "avr8_update_timer2_compare_mode: TODO; Toggle OC2%c on Compare Match\n", avr8_reg_name[reg]);
break;
case 2: // Clear OC2n on Compare Match
//verboselog(machine(), 0, "avr8_update_timer2_compare_mode: TODO; Clear OC2%c on Compare Match\n", avr8_reg_name[reg]);
break;
case 3: // Set OC2n on Compare Match
//verboselog(machine(), 0, "avr8_update_timer2_compare_mode: TODO; Set OC2%c on Compare Match\n", avr8_reg_name[reg]);
break;
}
break;
case Avr8::WGM2_PWM_PC:
switch(mode)
{
case 1: // Normal port operation, OC2n disconnected
//verboselog(machine(), 0, "avr8_update_timer2_compare_mode: TODO; OC2%c disconnected, normal port operation\n", avr8_reg_name[reg]);
break;
case 2: // Clear OC2n on match when up-counting, set when down-counting
//verboselog(machine(), 0, "avr8_update_timer2_compare_mode: TODO; Clear OC2%c on match when up-counting, set when down-counting\n", avr8_reg_name[reg]);
break;
case 3: // Set OC2n on match when up-counting, clear when down-counting
//verboselog(machine(), 0, "avr8_update_timer2_compare_mode: TODO; Set OC2%c on match when up-counting, clear when down-counting\n", avr8_reg_name[reg]);
break;
}
break;
case Avr8::WGM2_PWM_PC_CMP:
switch(mode)
{
case 1: // Toggle OC2n on compare match
//verboselog(machine(), 0, "avr8_update_timer2_compare_mode: TODO; Toggle OC2%c on compare match\n", avr8_reg_name[reg]);
break;
case 2: // Clear OC2n on match when up-counting, set when down-counting
//verboselog(machine(), 0, "avr8_update_timer2_compare_mode: TODO; Clear OC2%c on match when up-counting, set when down-counting\n", avr8_reg_name[reg]);
break;
case 3: // Set OC2n on match when up-counting, clear when down-counting
//verboselog(machine(), 0, "avr8_update_timer2_compare_mode: TODO; Set OC2%c on match when up-counting, clear when down-counting\n", avr8_reg_name[reg]);
break;
}
break;
case Avr8::WGM2_FAST_PWM:
switch(mode)
{
case 1: // Normal port operation, OC2n disconnected
//verboselog(machine(), 0, "avr8_update_timer2_compare_mode: TODO; OC2%c disconnected, normal port operation\n", avr8_reg_name[reg]);
break;
case 2: // Clear OC2n on match, set at BOTTOM
//verboselog(machine(), 0, "avr8_update_timer2_compare_mode: TODO; Clear OC2%c on match, set at BOTTOM\n", avr8_reg_name[reg]);
break;
case 3: // Set OC2n on match, clear at BOTTOM
//verboselog(machine(), 0, "avr8_update_timer2_compare_mode: TODO; Set OC2%c on match, clear at BOTTOM\n", avr8_reg_name[reg]);
break;
}
break;
case Avr8::WGM2_FAST_PWM_CMP:
switch(mode)
{
case 1: // Toggle OC2n on compare match
//verboselog(machine(), 0, "avr8_update_timer2_compare_mode: TODO; Toggle OC2%c on compare match\n", avr8_reg_name[reg]);
break;
case 2: // Clear OC2n on match, set at BOTTOM
//verboselog(machine(), 0, "avr8_update_timer2_compare_mode: TODO; Clear OC2%c on match, set at BOTTOM\n", avr8_reg_name[reg]);
break;
case 3: // Set OC2n on match, clear at BOTTOM
//verboselog(machine(), 0, "avr8_update_timer2_compare_mode: TODO; Set OC2%c on match, clear at BOTTOM\n", avr8_reg_name[reg]);
break;
}
break;
default:
break;
}
}
*/
}
static void avr8_update_timer1_clock_source(running_machine &machine)
{
craft_state *state = machine.driver_data<craft_state>();
attotime period;
switch(AVR8_TIMER2_CLOCK_SELECT)
{
case 0: // Counter stopped
period = attotime::never;
break;
case 1: // Clk/1; no prescaling
period = attotime::from_hz(MASTER_CLOCK);
break;
case 2: // Clk/8
period = attotime::from_hz(MASTER_CLOCK/8);
break;
case 3: // Clk/32
period = attotime::from_hz(MASTER_CLOCK/32);
break;
case 4: // Clk/64
period = attotime::from_hz(MASTER_CLOCK/64);
break;
case 5: // Clk/128
period = attotime::from_hz(MASTER_CLOCK/128);
break;
case 6: // T1 trigger, falling edge
case 7: // T1 trigger, rising edge
period = attotime::never;
verboselog(machine, 0, "avr8_update_timer1_clock_source: T1 Trigger mode not implemented yet\n");
break;
}
state->m_timer1_timer->adjust(period, 0, period);
}
static void avr8_changed_tccr1b(running_machine &machine, UINT8 data)
{
craft_state *state = machine.driver_data<craft_state>();
UINT8 oldtccr = AVR8_TCCR1B;
UINT8 newtccr = data;
UINT8 changed = newtccr ^ oldtccr;
state->m_regs[Avr8::REGIDX_TCCR1B] = newtccr;
if(changed & AVR8_TCCR1B_ICNC1_MASK)
{
// TODO
avr8_update_timer1_input_noise_canceler(machine);
}
if(changed & AVR8_TCCR1B_ICES1_MASK)
{
// TODO
avr8_update_timer1_input_edge_select(machine);
}
if(changed & AVR8_TCCR1B_WGM1_32_MASK)
{
// TODO
avr8_update_timer1_waveform_gen_mode(machine);
}
if(changed & AVR8_TCCR1B_CS_MASK)
{
avr8_update_timer1_clock_source(machine);
}
}
static void avr8_update_timer2_waveform_gen_mode(running_machine &machine)
{
craft_state *state = machine.driver_data<craft_state>();
state->m_timer2_top = 0;
switch(AVR8_WGM2)
{
case Avr8::WGM2_NORMAL:
case Avr8::WGM2_PWM_PC:
case Avr8::WGM2_FAST_PWM:
state->m_timer2_top = 0x00ff;
break;
case Avr8::WGM2_CTC_CMP:
case Avr8::WGM2_PWM_PC_CMP:
case Avr8::WGM2_FAST_PWM_CMP:
state->m_timer2_top = AVR8_OCR2A;
break;
default:
verboselog(machine, 0, "avr8_update_timer2_waveform_gen_mode: Unsupported waveform generation type: %d\n", AVR8_WGM2);
break;
}
}
static void avr8_changed_tccr2a(running_machine &machine, UINT8 data)
{
craft_state *state = machine.driver_data<craft_state>();
UINT8 oldtccr = AVR8_TCCR2A;
UINT8 newtccr = data;
UINT8 changed = newtccr ^ oldtccr;
if(changed & AVR8_TCCR2A_WGM2_10_MASK)
{
// TODO
avr8_update_timer2_waveform_gen_mode(machine);
}
}
static void avr8_update_timer2_clock_source(running_machine &machine)
{
craft_state *state = machine.driver_data<craft_state>();
attotime period;
switch(AVR8_TIMER2_CLOCK_SELECT)
{
case 0: // Counter stopped
period = attotime::never;
break;
case 1: // Clk/1; no prescaling
period = attotime::from_hz(MASTER_CLOCK);
break;
case 2: // Clk/8
period = attotime::from_hz(MASTER_CLOCK/8);
break;
case 3: // Clk/32
period = attotime::from_hz(MASTER_CLOCK/32);
break;
case 4: // Clk/64
period = attotime::from_hz(MASTER_CLOCK/64);
break;
case 5: // Clk/128
period = attotime::from_hz(MASTER_CLOCK/128);
break;
case 6: // Clk/256
period = attotime::from_hz(MASTER_CLOCK/256);
break;
case 7: // Clk/1024
period = attotime::from_hz(MASTER_CLOCK/1024);
break;
}
state->m_timer2_timer->adjust(period, 0, period);
}
static void avr8_timer2_force_output_compare(running_machine &machine, int reg)
{
// TODO
verboselog(machine, 0, "avr8_force_output_compare: TODO; should be forcing OC2%c\n", avr8_reg_name[reg]);
}
static void avr8_changed_tccr2b(running_machine &machine, UINT8 data)
{
craft_state *state = machine.driver_data<craft_state>();
UINT8 oldtccr = AVR8_TCCR2B;
UINT8 newtccr = data;
UINT8 changed = newtccr ^ oldtccr;
if(changed & AVR8_TCCR2B_FOC2A_MASK)
{
// TODO
avr8_timer2_force_output_compare(machine, AVR8_REG_A);
}
if(changed & AVR8_TCCR2B_FOC2B_MASK)
{
// TODO
avr8_timer2_force_output_compare(machine, AVR8_REG_B);
}
if(changed & AVR8_TCCR2B_WGM2_2_MASK)
{
// TODO
avr8_update_timer2_waveform_gen_mode(machine);
}
if(changed & AVR8_TCCR2B_CS_MASK)
{
avr8_update_timer2_clock_source(machine);
}
}
static void avr8_update_ocr1(running_machine &machine, UINT16 newval, UINT8 reg)
{
craft_state *state = machine.driver_data<craft_state>();
UINT8 *p_reg_h = (reg == AVR8_REG_A) ? &AVR8_OCR1AH : &AVR8_OCR1BH;
UINT8 *p_reg_l = (reg == AVR8_REG_A) ? &AVR8_OCR1AL : &AVR8_OCR1BL;
*p_reg_h = (UINT8)(newval >> 8);
*p_reg_l = (UINT8)newval;
// TODO
verboselog(machine, 0, "avr8_update_ocr1: TODO: new OCR1%c = %04x\n", avr8_reg_name[reg], newval);
}
WRITE8_MEMBER(craft_state::avr8_write)
{
craft_state *state = machine().driver_data<craft_state>();
if(offset <= Avr8::REGIDX_R31)
{
m_regs[offset] = data;
return;
}
switch( offset )
{
case Avr8::REGIDX_OCR1BH:
verboselog(machine(), 0, "AVR8: OCR1BH = %02x\n", data );
avr8_update_ocr1(machine(), (AVR8_OCR1B & 0x00ff) | (data << 8), AVR8_REG_B);
break;
case Avr8::REGIDX_OCR1BL:
verboselog(machine(), 0, "AVR8: OCR1BL = %02x\n", data );
avr8_update_ocr1(machine(), (AVR8_OCR1B & 0xff00) | data, AVR8_REG_B);
break;
case Avr8::REGIDX_OCR1AH:
verboselog(machine(), 0, "AVR8: OCR1AH = %02x\n", data );
avr8_update_ocr1(machine(), (AVR8_OCR1A & 0x00ff) | (data << 8), AVR8_REG_A);
break;
case Avr8::REGIDX_OCR1AL:
verboselog(machine(), 0, "AVR8: OCR1AL = %02x\n", data );
avr8_update_ocr1(machine(), (AVR8_OCR1A & 0xff00) | data, AVR8_REG_A);
break;
case Avr8::REGIDX_TCCR1B:
verboselog(machine(), 0, "AVR8: TCCR1B = %02x\n", data );
avr8_changed_tccr1b(machine(), data);
break;
case Avr8::REGIDX_TCCR1A:
verboselog(machine(), 0, "AVR8: TCCR1A = %02x\n", data );
avr8_changed_tccr1a(machine(), data);
break;
case Avr8::REGIDX_TIMSK1:
verboselog(machine(), 0, "AVR8: TIMSK1 = %02x\n", data );
avr8_change_timsk1(machine(), data);
break;
case Avr8::REGIDX_TCCR2B:
verboselog(machine(), 0, "AVR8: TCCR2B = %02x\n", data );
avr8_changed_tccr2b(machine(), data);
break;
case Avr8::REGIDX_TCCR2A:
verboselog(machine(), 0, "AVR8: TCCR2A = %02x\n", data );
avr8_changed_tccr2a(machine(), data);
break;
case Avr8::REGIDX_TCNT2:
//verboselog(machine(), 0, "AVR8: TCNT2 = %02x\n", data );
AVR8_TCNT2 = data;
break;
case Avr8::REGIDX_GTCCR:
//verboselog(machine(), 0, "AVR8: GTCCR = %02x\n", data );
// TODO
break;
case Avr8::REGIDX_SPL:
case Avr8::REGIDX_SPH:
case Avr8::REGIDX_SREG:
m_regs[offset] = data;
break;
case Avr8::REGIDX_SPSR:
case AVR8_REGIDX_SPSR:
avr8_change_spsr(machine(), data);
break;
case Avr8::REGIDX_SPCR:
case AVR8_REGIDX_SPCR:
avr8_change_spcr(machine(), data);
break;
case Avr8::REGIDX_PORTD:
case AVR8_REGIDX_SPDR:
// TODO
break;
case AVR8_REGIDX_EECR:
if (data & AVR8_EECR_EERE)
{
UINT16 addr = (m_regs[AVR8_REGIDX_EEARH] & AVR8_EEARH_MASK) << 8;
addr |= m_regs[AVR8_REGIDX_EEARL];
m_regs[AVR8_REGIDX_EEDR] = m_eeprom[addr];
}
break;
case AVR8_REGIDX_EEARL:
case AVR8_REGIDX_EEARH:
m_regs[offset] = data;
break;
case AVR8_REGIDX_PORTD:
avr8_change_port(machine(), AVR8_REG_D, data);
break;
case Avr8::REGIDX_DDRD:
case AVR8_REGIDX_DDRD:
avr8_change_ddr(machine(), AVR8_REG_D, data);
break;
case Avr8::REGIDX_DDRC:
case AVR8_REGIDX_PORTC:
avr8_change_port(machine(), AVR8_REG_C, data);
break;
case AVR8_REGIDX_DDRC:
avr8_change_ddr(machine(), AVR8_REG_C, data);
break;
case Avr8::REGIDX_PORTB:
case AVR8_REGIDX_PORTB:
avr8_change_port(machine(), AVR8_REG_B, data);
break;
case Avr8::REGIDX_DDRB:
case AVR8_REGIDX_DDRB:
avr8_change_ddr(machine(), AVR8_REG_B, data);
break;
@ -967,19 +378,11 @@ void craft_state::machine_reset()
{
craft_state *state = machine().driver_data<craft_state>();
AVR8_TIMSK1 = 0;
AVR8_OCR1AH = 0;
AVR8_OCR1AL = 0;
AVR8_OCR1BH = 0;
AVR8_OCR1BL = 0;
AVR8_ICR1H = 0;
AVR8_ICR1L = 0;
AVR8_TCNT1H = 0;
AVR8_TCNT1L = 0;
state->dac = machine().device<dac_device>("dac");
state->dac->write_unsigned8(0x00);
state->m_eeprom = memregion("eeprom")->base();
}
static MACHINE_CONFIG_START( craft, craft_state )

View File

@ -1,7 +1,6 @@
#include "emu.h"
#include "cpu/avr8/avr8.h"
#include "machine/avr8.h"
#include "sound/dac.h"
#include "imagedev/cartslot.h"

View File

@ -1,299 +0,0 @@
#ifndef __EMU_MACHINE_AVR8_H__
#define __EMU_MACHINE_AVR8_H__
// Helpful enums and defines for the Atmel 8-bit AVR series of microcontrollers
namespace Avr8
{
enum
{
REGIDX_R0 = 0,
REGIDX_R1,
REGIDX_R2,
REGIDX_R3,
REGIDX_R4,
REGIDX_R5,
REGIDX_R6,
REGIDX_R7,
REGIDX_R8,
REGIDX_R9,
REGIDX_R10,
REGIDX_R11,
REGIDX_R12,
REGIDX_R13,
REGIDX_R14,
REGIDX_R15,
REGIDX_R16,
REGIDX_R17,
REGIDX_R18,
REGIDX_R19,
REGIDX_R20,
REGIDX_R21,
REGIDX_R22,
REGIDX_R23,
REGIDX_R24,
REGIDX_R25,
REGIDX_R26,
REGIDX_R27,
REGIDX_R28,
REGIDX_R29,
REGIDX_R30,
REGIDX_R31,
REGIDX_PINB = 0x23,
REGIDX_DDRB,
REGIDX_PORTB,
REGIDX_PINC,
REGIDX_DDRC,
REGIDX_PORTC,
REGIDX_PIND,
REGIDX_DDRD,
REGIDX_PORTD,
REGIDX_TIFR0 = 0x35,
REGIDX_TIFR1,
REGIDX_TIFR2,
REGIDX_PCIFR = 0x3b,
REGIDX_EIFR,
REGIDX_EIMSK,
REGIDX_GPIOR0,
REGIDX_EECR,
REGIDX_EEDR,
REGIDX_EEARL,
REGIDX_EEARH,
REGIDX_GTCCR,
REGIDX_TCCR0A,
REGIDX_TCCR0B,
REGIDX_TCNT0,
REGIDX_OCR0A,
REGIDX_OCR0B,
REGIDX_GPIOR1 = 0x4a,
REGIDX_GPIOR2,
REGIDX_SPCR,
REGIDX_SPSR,
REGIDX_SPDR,
REGIDX_ACSR = 0x50,
REGIDX_SMCR = 0x53,
REGIDX_MCUSR,
REGIDX_MCUCR,
REGIDX_SPMCSR = 0x57,
REGIDX_SPL = 0x5d,
REGIDX_SPH,
REGIDX_SREG,
REGIDX_WDTCSR,
REGIDX_CLKPR,
REGIDX_PRR = 0x64,
REGIDX_OSCCAL = 0x66,
REGIDX_PCICR = 0x68,
REGIDX_EICRA,
REGIDX_PCMSK0 = 0x6B,
REGIDX_PCMSK1,
REGIDX_PCMSK2,
REGIDX_TIMSK0,
REGIDX_TIMSK1,
REGIDX_TIMSK2,
REGIDX_ADCL = 0x78,
REGIDX_ADCH,
REGIDX_ADCSRA,
REGIDX_ADCSRB,
REGIDX_ADMUX,
REGIDX_DIDR0 = 0x7e,
REGIDX_DIDR1,
REGIDX_TCCR1A,
REGIDX_TCCR1B,
REGIDX_TCCR1C,
REGIDX_TCNT1L = 0x84,
REGIDX_TCNT1H,
REGIDX_ICR1L,
REGIDX_ICR1H,
REGIDX_OCR1AL,
REGIDX_OCR1AH,
REGIDX_OCR1BL,
REGIDX_OCR1BH,
REGIDX_TCCR2A = 0xb0,
REGIDX_TCCR2B,
REGIDX_TCNT2,
REGIDX_OCR2A,
REGIDX_OCR2B,
REGIDX_ASSR = 0xb6,
REGIDX_TWBR = 0xb8,
REGIDX_TWSR,
REGIDX_TWAR,
REGIDX_TWDR,
REGIDX_TWCR,
REGIDX_TWAMR,
REGIDX_UCSR0A = 0xc0,
REGIDX_UCSR0B,
REGIDX_UCSR0C,
REGIDX_UBRR0L = 0xc4,
REGIDX_UBRR0H,
REGIDX_UDR0
};
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
{
WGM2_NORMAL = 0,
WGM2_PWM_PC,
WGM2_CTC_CMP,
WGM2_FAST_PWM,
WGM2_RESERVED0,
WGM2_PWM_PC_CMP,
WGM2_RESERVED1,
WGM2_FAST_PWM_CMP
};
} // namespace AVR8
#define AVR8_OCR1BH (state->m_regs[Avr8::REGIDX_OCR1BH])
#define AVR8_OCR1BL (state->m_regs[Avr8::REGIDX_OCR1BL])
#define AVR8_OCR1AH (state->m_regs[Avr8::REGIDX_OCR1AH])
#define AVR8_OCR1AL (state->m_regs[Avr8::REGIDX_OCR1AL])
#define AVR8_ICR1H (state->m_regs[Avr8::REGIDX_ICR1H])
#define AVR8_ICR1L (state->m_regs[Avr8::REGIDX_ICR1L])
#define AVR8_TCNT1H (state->m_regs[Avr8::REGIDX_TCNT1H])
#define AVR8_TCNT1L (state->m_regs[Avr8::REGIDX_TCNT1L])
#define AVR8_SREG_I 0x80
#define AVR8_TCCR1B (state->m_regs[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 0x03
#define AVR8_TCCR1B_CS_SHIFT 0
#define AVR8_TCCR1A (state->m_regs[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 (state->m_regs[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_TCCR2B (state->m_regs[Avr8::REGIDX_TCCR1B])
#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 0x03
#define AVR8_TCCR2B_CS_SHIFT 0
#define AVR8_TIMER2_CLOCK_SELECT ((AVR8_TCCR2B & AVR8_TCCR2B_CS_MASK) >> AVR8_TCCR2B_CS_SHIFT)
#define AVR8_TCCR2A (state->m_regs[Avr8::REGIDX_TCCR1A])
#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_TCCR1A_WGM2_10_MASK)
#define AVR8_SPSR (state->m_regs[Avr8::REGIDX_SPSR])
#define AVR8_SPSR_SPIF_MASK 0x80
#define AVR8_SPSR_SPIF_SHIFT 7
#define AVR8_SPSR_SPR2X_MASK 0x01
#define AVR8_SPSR_SPR2X (AVR8_SPSR & AVR8_SPSR_SPR2X_MASK)
#define AVR8_SPCR (state->m_regs[Avr8::REGIDX_SPCR])
#define AVR8_SPCR_SPIE_MASK 0x80
#define AVR8_SPCR_SPE_MASK 0x40
#define AVR8_SPCR_DORD_MASK 0x20
#define AVR8_SPCR_MSTR_MASK 0x10
#define AVR8_SPCR_CPOL_MASK 0x08
#define AVR8_SPCR_CPHA_MASK 0x04
#define AVR8_SPCR_SPR_MASK 0x03
#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_TIFR1 (state->m_regs[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_DDRD (state->m_regs[Avr8::REGIDX_DDRD])
#define AVR8_DDRC (state->m_regs[Avr8::REGIDX_DDRC])
#define AVR8_PORTB (state->m_regs[Avr8::REGIDX_PORTB])
#define AVR8_DDRB (state->m_regs[Avr8::REGIDX_DDRB])
#define AVR8_OCR1A ((AVR8_OCR1AH << 8) | AVR8_OCR1AL)
#define AVR8_OCR1B ((AVR8_OCR1BH << 8) | AVR8_OCR1BL)
#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_OCR2B state->m_regs[Avr8::REGIDX_OCR2B]
#define AVR8_OCR2A state->m_regs[Avr8::REGIDX_OCR2A]
#define AVR8_TCNT2 state->m_regs[Avr8::REGIDX_TCNT2]
#define AVR8_WGM2 (((AVR8_TCCR2B & 0x08) >> 1) | (AVR8_TCCR2A & 0x03))
#endif // __EMU_MACHINE_AVR8_H__