mirror of
https://github.com/holub/mame
synced 2025-04-22 08:22:15 +03:00
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:
parent
9dfaad4477
commit
4212614f83
1
.gitattributes
vendored
1
.gitattributes
vendored
@ -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
@ -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__ */
|
||||
|
@ -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 )
|
||||
|
@ -1,7 +1,6 @@
|
||||
|
||||
#include "emu.h"
|
||||
#include "cpu/avr8/avr8.h"
|
||||
#include "machine/avr8.h"
|
||||
#include "sound/dac.h"
|
||||
#include "imagedev/cartslot.h"
|
||||
|
||||
|
@ -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__
|
Loading…
Reference in New Issue
Block a user