mirror of
https://github.com/holub/mame
synced 2025-04-23 00:39:36 +03:00
-avr8: Fixed assorted Timer 0 and Timer 1 bugs. [Ryan Holtz]
-avr8dasm: Fixed erroneous disassembly of CBI, SBI, SBIS, and SBIC opcodes. [Ryan Holtz] New working machines -------------------- Power Ninja Action Challenge [Ryan Holtz]
This commit is contained in:
parent
735752cea8
commit
e04f490e4b
@ -92,7 +92,7 @@
|
||||
#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 \
|
||||
LOG_OSC | LOG_PINCHG | LOG_EXTMEM | LOG_ADC | LOG_DIGINPUT | LOG_ASYNC | LOG_TWI | LOG_UART)
|
||||
| LOG_OSC | LOG_PINCHG | LOG_EXTMEM | LOG_ADC | LOG_DIGINPUT | LOG_ASYNC | LOG_TWI | LOG_UART)
|
||||
|
||||
#define VERBOSE (0)
|
||||
#include "logmacro.h"
|
||||
@ -870,6 +870,7 @@ void avr8_device::device_start()
|
||||
// Misc.
|
||||
save_item(NAME(m_addr_mask));
|
||||
save_item(NAME(m_interrupt_pending));
|
||||
save_item(NAME(m_opcycles));
|
||||
|
||||
// set our instruction counter
|
||||
set_icountptr(m_icount);
|
||||
@ -1040,7 +1041,6 @@ inline uint8_t avr8_device::pop()
|
||||
|
||||
void avr8_device::set_irq_line(uint16_t vector, int state)
|
||||
{
|
||||
// Horrible hack, not accurate
|
||||
if (state)
|
||||
{
|
||||
if (SREG_R(AVR8_SREG_I))
|
||||
@ -1058,17 +1058,16 @@ void avr8_device::set_irq_line(uint16_t vector, int state)
|
||||
}
|
||||
}
|
||||
|
||||
class CInterruptCondition
|
||||
struct interrupt_condition
|
||||
{
|
||||
public:
|
||||
uint8_t m_intindex;
|
||||
uint8_t m_intreg;
|
||||
uint8_t m_intmask;
|
||||
uint8_t m_regindex;
|
||||
uint8_t m_regmask;
|
||||
uint8_t m_intindex;
|
||||
uint8_t m_intreg;
|
||||
uint8_t m_intmask;
|
||||
uint8_t m_regindex;
|
||||
uint8_t m_regmask;
|
||||
};
|
||||
|
||||
static const CInterruptCondition s_int_conditions[AVR8_INTIDX_COUNT] =
|
||||
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 },
|
||||
@ -1085,7 +1084,7 @@ static const CInterruptCondition s_int_conditions[AVR8_INTIDX_COUNT] =
|
||||
|
||||
void avr8_device::update_interrupt(int source)
|
||||
{
|
||||
const CInterruptCondition &condition = s_int_conditions[source];
|
||||
const interrupt_condition &condition = s_int_conditions[source];
|
||||
|
||||
int intstate = 0;
|
||||
if (m_r[condition.m_intreg] & condition.m_intmask)
|
||||
@ -1101,7 +1100,7 @@ void avr8_device::update_interrupt(int source)
|
||||
|
||||
void atmega328_device::update_interrupt(int source)
|
||||
{
|
||||
const CInterruptCondition &condition = s_int_conditions[source];
|
||||
const interrupt_condition &condition = s_int_conditions[source];
|
||||
|
||||
int intstate = 0;
|
||||
if (m_r[condition.m_intreg] & condition.m_intmask)
|
||||
@ -1115,7 +1114,7 @@ void atmega328_device::update_interrupt(int source)
|
||||
}
|
||||
}
|
||||
|
||||
static const CInterruptCondition s_mega644_int_conditions[AVR8_INTIDX_COUNT] =
|
||||
static const interrupt_condition s_mega644_int_conditions[AVR8_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 },
|
||||
@ -1132,7 +1131,7 @@ static const CInterruptCondition s_mega644_int_conditions[AVR8_INTIDX_COUNT] =
|
||||
|
||||
void atmega644_device::update_interrupt(int source)
|
||||
{
|
||||
const CInterruptCondition &condition = s_mega644_int_conditions[source];
|
||||
const interrupt_condition &condition = s_mega644_int_conditions[source];
|
||||
|
||||
int intstate = 0;
|
||||
if (m_r[condition.m_intreg] & condition.m_intmask)
|
||||
@ -1149,7 +1148,7 @@ void atmega644_device::update_interrupt(int source)
|
||||
//TODO: review this!
|
||||
void atmega1280_device::update_interrupt(int source)
|
||||
{
|
||||
const CInterruptCondition &condition = s_mega644_int_conditions[source];
|
||||
const interrupt_condition &condition = s_mega644_int_conditions[source];
|
||||
|
||||
int intstate = 0;
|
||||
if (m_r[condition.m_intreg] & condition.m_intmask)
|
||||
@ -1166,7 +1165,7 @@ void atmega1280_device::update_interrupt(int source)
|
||||
//TODO: review this!
|
||||
void atmega2560_device::update_interrupt(int source)
|
||||
{
|
||||
const CInterruptCondition &condition = s_mega644_int_conditions[source];
|
||||
const interrupt_condition &condition = s_mega644_int_conditions[source];
|
||||
|
||||
int intstate = 0;
|
||||
if (m_r[condition.m_intreg] & condition.m_intmask)
|
||||
@ -1224,20 +1223,17 @@ void avr8_device::timer_tick()
|
||||
}
|
||||
}
|
||||
|
||||
// uint8_t ocr0[2] = { m_r[AVR8_REGIDX_OCR0A], m_r[AVR8_REGIDX_OCR0B] };
|
||||
//TODO uint8_t ocf0[2] = { (1 << AVR8_TIFR0_OCF0A_SHIFT), (1 << AVR8_TIFR4_OCF0B_SHIFT) };
|
||||
//TODO uint8_t int0[2] = { AVR8_INTIDX_OCF0A, AVR8_INTIDX_OCF0B };
|
||||
|
||||
#define LOG_TIMER_0 0
|
||||
#define LOG_TIMER_5 0
|
||||
// Timer 0 Handling
|
||||
void avr8_device::timer0_tick()
|
||||
{
|
||||
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_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);
|
||||
|
||||
uint8_t count = m_r[AVR8_REGIDX_TCNT0];
|
||||
int32_t increment = m_timer_increment[0];
|
||||
count++;
|
||||
|
||||
switch (AVR8_WGM0)
|
||||
{
|
||||
@ -1253,10 +1249,16 @@ void avr8_device::timer0_tick()
|
||||
switch (AVR8_TCCR0A_COM0B)
|
||||
{
|
||||
case 0: /* Normal Operation */
|
||||
if (count == m_timer_top[0])
|
||||
if (count == AVR8_OCR0A)
|
||||
{
|
||||
LOGMASKED(LOG_TIMER0, "%s: timer0: Set normal OC0B behavior\n", machine().describe_context());
|
||||
m_timer_top[0] = 0;
|
||||
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;
|
||||
|
||||
@ -1290,26 +1292,23 @@ void avr8_device::timer0_tick()
|
||||
break;
|
||||
|
||||
case WGM02_FAST_PWM:
|
||||
LOGMASKED(LOG_TIMER0 | LOG_UNKNOWN, "%s: WGM02_FAST_PWM: Unimplemented timer0 waveform generation mode\n", machine().describe_context());
|
||||
break;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
count = count & 0xff;
|
||||
|
||||
count += increment;
|
||||
m_r[AVR8_REGIDX_TCNT0] = count & 0xff;
|
||||
m_r[AVR8_REGIDX_TCNT0] = count;
|
||||
}
|
||||
|
||||
void avr8_device::changed_tccr0a(uint8_t data)
|
||||
@ -1379,11 +1378,15 @@ inline void avr8_device::timer1_tick()
|
||||
static const uint8_t s_int1[2] = { AVR8_INTIDX_OCF1A, AVR8_INTIDX_OCF1B };
|
||||
int32_t increment = m_timer_increment[1];
|
||||
|
||||
LOGMASKED(LOG_TIMER1_TICK, "%s: AVR8_WGM1: %d\n", machine().describe_context(), AVR8_WGM1);
|
||||
|
||||
for (int32_t reg = AVR8_REG_A; reg <= AVR8_REG_B; reg++)
|
||||
{
|
||||
switch (m_wgm1)
|
||||
{
|
||||
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)
|
||||
{
|
||||
m_r[AVR8_REGIDX_TIFR1] |= AVR8_TIFR1_TOV1_MASK;
|
||||
@ -1409,9 +1412,6 @@ inline void avr8_device::timer1_tick()
|
||||
m_r[AVR8_REGIDX_TIFR1] &= ~AVR8_TIFR1_TOV1_MASK;
|
||||
update_interrupt(AVR8_INTIDX_TOV1);
|
||||
}
|
||||
|
||||
m_r[AVR8_REGIDX_TIFR1] &= ~s_ocf1[reg];
|
||||
update_interrupt(s_int1[reg]);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -1882,7 +1882,7 @@ void avr8_device::update_timer_clock_source(uint8_t t, uint8_t clock_select)
|
||||
};
|
||||
m_timer_prescale[t] = s_prescale_values[(t == 2) ? 1 : 0][clock_select];
|
||||
|
||||
LOGMASKED((LOG_TIMER0 + t), "%s: update_timer_clock_source: t = %d, cs = %d\n", t, machine().describe_context(), clock_select);
|
||||
LOGMASKED((LOG_TIMER0 + t), "%s: update_timer_clock_source: t = %d, cs = %d\n", machine().describe_context(), t, clock_select);
|
||||
|
||||
if (m_timer_prescale[t] == 0xffff)
|
||||
{
|
||||
@ -2250,56 +2250,67 @@ void avr8_device::regs_w(offs_t offset, uint8_t data)
|
||||
break;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
@ -2327,12 +2338,12 @@ void avr8_device::regs_w(offs_t offset, uint8_t data)
|
||||
|
||||
case AVR8_REGIDX_OCR0A:
|
||||
LOGMASKED(LOG_TIMER0, "%s: OCR0A = %02x\n", machine().describe_context(), data);
|
||||
update_ocr0(AVR8_OCR0A, AVR8_REG_A);
|
||||
update_ocr0(data, AVR8_REG_A);
|
||||
break;
|
||||
|
||||
case AVR8_REGIDX_OCR0B:
|
||||
LOGMASKED(LOG_TIMER0, "%s: OCR0B = %02x\n", machine().describe_context(), data);
|
||||
update_ocr0(AVR8_OCR0B, AVR8_REG_B);
|
||||
update_ocr0(data, AVR8_REG_B);
|
||||
break;
|
||||
|
||||
case AVR8_REGIDX_TIFR0:
|
||||
@ -2408,7 +2419,12 @@ void avr8_device::regs_w(offs_t offset, uint8_t data)
|
||||
break;
|
||||
|
||||
case AVR8_REGIDX_GPIOR1:
|
||||
LOGMASKED(LOG_GPIO, "%s: GPIOR1 Write: %02x\n", machine().describe_context(), data);
|
||||
m_r[offset] = data;
|
||||
break;
|
||||
|
||||
case AVR8_REGIDX_GPIOR2:
|
||||
LOGMASKED(LOG_GPIO, "%s: GPIOR2 Write: %02x\n", machine().describe_context(), data);
|
||||
m_r[offset] = data;
|
||||
break;
|
||||
|
||||
@ -2813,6 +2829,8 @@ void avr8_device::regs_w(offs_t offset, uint8_t data)
|
||||
|
||||
uint8_t avr8_device::regs_r(offs_t offset)
|
||||
{
|
||||
uint8_t data = m_r[offset];
|
||||
|
||||
switch (offset)
|
||||
{
|
||||
case AVR8_REGIDX_R0:
|
||||
@ -2847,7 +2865,7 @@ uint8_t avr8_device::regs_r(offs_t offset)
|
||||
case AVR8_REGIDX_R29:
|
||||
case AVR8_REGIDX_R30:
|
||||
case AVR8_REGIDX_R31:
|
||||
return m_r[offset];
|
||||
return data;
|
||||
|
||||
case AVR8_REGIDX_PINA:
|
||||
// TODO: account for DDRA
|
||||
@ -2904,7 +2922,7 @@ uint8_t avr8_device::regs_r(offs_t offset)
|
||||
case AVR8_REGIDX_PORTJ:
|
||||
case AVR8_REGIDX_PORTK:
|
||||
case AVR8_REGIDX_PORTL:
|
||||
return m_r[offset];
|
||||
return data;
|
||||
|
||||
case AVR8_REGIDX_DDRA:
|
||||
case AVR8_REGIDX_DDRB:
|
||||
@ -2917,19 +2935,25 @@ uint8_t avr8_device::regs_r(offs_t offset)
|
||||
case AVR8_REGIDX_DDRJ:
|
||||
case AVR8_REGIDX_DDRK:
|
||||
case AVR8_REGIDX_DDRL:
|
||||
return m_r[offset];
|
||||
return data;
|
||||
|
||||
// EEPROM registers
|
||||
case AVR8_REGIDX_EECR:
|
||||
case AVR8_REGIDX_EEDR:
|
||||
return m_r[offset];
|
||||
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
|
||||
@ -2939,12 +2963,26 @@ uint8_t avr8_device::regs_r(offs_t offset)
|
||||
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:
|
||||
// case AVR8_REGIDX_TIMSK3: // TODO: needed for Replicator 1
|
||||
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:
|
||||
return m_r[offset];
|
||||
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:
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -2,7 +2,7 @@
|
||||
// copyright-holders:Ryan Holtz
|
||||
/**********************************************************************
|
||||
|
||||
"Craft" demo platform by Linus Akesson
|
||||
ATmega88-based demo platforms by Linus Åkesson
|
||||
|
||||
**********************************************************************/
|
||||
|
||||
@ -14,8 +14,6 @@
|
||||
#include "emupal.h"
|
||||
#include "speaker.h"
|
||||
|
||||
#define MASTER_CLOCK 20000000
|
||||
|
||||
#define VISIBLE_CYCLES 480
|
||||
#define HSYNC_CYCLES 155
|
||||
#define LINE_CYCLES (VISIBLE_CYCLES + HSYNC_CYCLES)
|
||||
@ -25,15 +23,72 @@
|
||||
#define CYCLES_PER_FRAME (LINES_PER_FRAME * LINE_CYCLES)
|
||||
#define PIXELS_PER_FRAME (CYCLES_PER_FRAME)
|
||||
|
||||
class craft_state : public driver_device
|
||||
class lft_state : public driver_device
|
||||
{
|
||||
public:
|
||||
lft_state(const machine_config &mconfig, device_type type, const char *tag)
|
||||
: driver_device(mconfig, type, tag)
|
||||
, m_maincpu(*this, "maincpu")
|
||||
, m_dac(*this, "dac")
|
||||
{
|
||||
}
|
||||
|
||||
void base_config(machine_config &config);
|
||||
|
||||
protected:
|
||||
virtual void machine_start() override;
|
||||
virtual void machine_reset() override;
|
||||
|
||||
virtual uint32_t master_clock() const = 0;
|
||||
|
||||
void prg_map(address_map &map);
|
||||
void data_map(address_map &map);
|
||||
void io_map(address_map &map);
|
||||
|
||||
uint8_t port_r(offs_t offset);
|
||||
void port_w(offs_t offset, uint8_t data);
|
||||
|
||||
virtual void port_update(const offs_t offset, const uint8_t old, const uint8_t data) = 0;
|
||||
|
||||
required_device<avr8_device> m_maincpu;
|
||||
required_device<dac_byte_interface> m_dac;
|
||||
|
||||
enum port : uint8_t
|
||||
{
|
||||
PORT_A,
|
||||
PORT_B,
|
||||
PORT_C,
|
||||
PORT_D,
|
||||
|
||||
PORT_COUNT
|
||||
};
|
||||
|
||||
uint8_t m_ports[PORT_COUNT];
|
||||
};
|
||||
|
||||
class powernin_state : public lft_state
|
||||
{
|
||||
public:
|
||||
powernin_state(const machine_config &mconfig, device_type type, const char *tag)
|
||||
: lft_state(mconfig, type, tag)
|
||||
{
|
||||
}
|
||||
|
||||
void powernin(machine_config &config);
|
||||
|
||||
private:
|
||||
virtual uint32_t master_clock() const override { return 8000000; }
|
||||
|
||||
virtual void port_update(const offs_t offset, const uint8_t old, const uint8_t data) override;
|
||||
};
|
||||
|
||||
class craft_state : public lft_state
|
||||
{
|
||||
public:
|
||||
craft_state(const machine_config &mconfig, device_type type, const char *tag)
|
||||
: driver_device(mconfig, type, tag)
|
||||
, m_maincpu(*this, "maincpu")
|
||||
: lft_state(mconfig, type, tag)
|
||||
, m_screen(*this, "screen")
|
||||
, m_palette(*this, "palette")
|
||||
, m_dac(*this, "dac")
|
||||
{
|
||||
}
|
||||
|
||||
@ -43,29 +98,20 @@ private:
|
||||
virtual void machine_start() override;
|
||||
virtual void machine_reset() override;
|
||||
|
||||
void craft_prg_map(address_map &map);
|
||||
void craft_data_map(address_map &map);
|
||||
void craft_io_map(address_map &map);
|
||||
virtual uint32_t master_clock() const override { return 20000000; }
|
||||
|
||||
uint8_t port_r(offs_t offset);
|
||||
void port_w(offs_t offset, uint8_t data);
|
||||
virtual void port_update(const offs_t offset, const uint8_t old, const uint8_t data) override;
|
||||
|
||||
void init_palette(palette_device &palette) const;
|
||||
void video_update();
|
||||
uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
|
||||
|
||||
required_device<avr8_device> m_maincpu;
|
||||
required_device<screen_device> m_screen;
|
||||
required_device<palette_device> m_palette;
|
||||
required_device<dac_byte_interface> m_dac;
|
||||
|
||||
uint32_t m_last_cycles;
|
||||
uint64_t m_frame_start_cycle;
|
||||
|
||||
uint8_t m_port_b;
|
||||
uint8_t m_port_c;
|
||||
uint8_t m_port_d;
|
||||
|
||||
uint8_t m_latched_color;
|
||||
std::unique_ptr<uint8_t[]> m_pixels;
|
||||
};
|
||||
@ -74,79 +120,73 @@ private:
|
||||
// GPIO
|
||||
//**************************************************************************
|
||||
|
||||
uint8_t craft_state::port_r(offs_t offset)
|
||||
uint8_t lft_state::port_r(offs_t offset)
|
||||
{
|
||||
switch (offset)
|
||||
{
|
||||
case 0x00: // Port A
|
||||
break;
|
||||
case 0x01: // Port B
|
||||
return m_port_b;
|
||||
case 0x02: // Port C
|
||||
return m_port_c;
|
||||
case 0x03: // Port D
|
||||
return m_port_d;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return m_ports[offset];
|
||||
}
|
||||
|
||||
void craft_state::port_w(offs_t offset, uint8_t data)
|
||||
void lft_state::port_w(offs_t offset, uint8_t data)
|
||||
{
|
||||
const uint8_t old = m_ports[offset];
|
||||
m_ports[offset] = data;
|
||||
port_update(offset, old, data);
|
||||
}
|
||||
|
||||
void craft_state::port_update(const offs_t offset, const uint8_t old, const uint8_t data)
|
||||
{
|
||||
const uint8_t changed = data ^ old;
|
||||
switch (offset)
|
||||
{
|
||||
case AVR8_IO_PORTA:
|
||||
break;
|
||||
case AVR8_IO_PORTA:
|
||||
break;
|
||||
|
||||
case AVR8_IO_PORTB:
|
||||
case AVR8_IO_PORTB:
|
||||
if (BIT(changed, 1) && BIT(data, 1))
|
||||
{
|
||||
uint8_t old_port_b = m_port_b;
|
||||
uint8_t pins = data;
|
||||
uint8_t changed = pins ^ old_port_b;
|
||||
if (BIT(changed, 1) && BIT(data, 1))
|
||||
{
|
||||
m_frame_start_cycle = machine().time().as_ticks(MASTER_CLOCK);
|
||||
video_update();
|
||||
}
|
||||
if (BIT(changed, 3))
|
||||
{
|
||||
video_update();
|
||||
m_latched_color = (pins & 0x08) ? (m_port_c & 0x3f) : 0x3f;
|
||||
}
|
||||
m_port_b = data;
|
||||
break;
|
||||
}
|
||||
|
||||
case AVR8_IO_PORTC:
|
||||
m_frame_start_cycle = machine().time().as_ticks(master_clock());
|
||||
video_update();
|
||||
m_port_c = data;
|
||||
m_latched_color = m_port_c;
|
||||
break;
|
||||
}
|
||||
if (BIT(changed, 3))
|
||||
{
|
||||
video_update();
|
||||
m_latched_color = (data & 0x08) ? (m_ports[PORT_C] & 0x3f) : 0x3f;
|
||||
}
|
||||
break;
|
||||
|
||||
case AVR8_IO_PORTD:
|
||||
m_port_d = data;
|
||||
m_dac->write((data & 0x02) | ((data & 0xf4) >> 2));
|
||||
break;
|
||||
case AVR8_IO_PORTC:
|
||||
video_update();
|
||||
m_latched_color = data;
|
||||
break;
|
||||
|
||||
case AVR8_IO_PORTD:
|
||||
m_dac->write((data & 0x02) | ((data & 0xf4) >> 2));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void powernin_state::port_update(const offs_t offset, const uint8_t old, const uint8_t data)
|
||||
{
|
||||
if (offset == AVR8_IO_PORTD)
|
||||
m_dac->write(data);
|
||||
}
|
||||
|
||||
//**************************************************************************
|
||||
// MEMORY
|
||||
//**************************************************************************
|
||||
|
||||
void craft_state::craft_prg_map(address_map &map)
|
||||
void lft_state::prg_map(address_map &map)
|
||||
{
|
||||
map(0x0000, 0x1fff).rom();
|
||||
}
|
||||
|
||||
void craft_state::craft_data_map(address_map &map)
|
||||
void lft_state::data_map(address_map &map)
|
||||
{
|
||||
map(0x0100, 0x04ff).ram();
|
||||
}
|
||||
|
||||
void craft_state::craft_io_map(address_map &map)
|
||||
void lft_state::io_map(address_map &map)
|
||||
{
|
||||
map(AVR8_IO_PORTA, AVR8_IO_PORTD).rw(FUNC(craft_state::port_r), FUNC(craft_state::port_w));
|
||||
map(AVR8_IO_PORTA, AVR8_IO_PORTD).rw(FUNC(lft_state::port_r), FUNC(lft_state::port_w));
|
||||
}
|
||||
|
||||
//**************************************************************************
|
||||
@ -166,7 +206,7 @@ void craft_state::init_palette(palette_device &palette) const
|
||||
|
||||
void craft_state::video_update()
|
||||
{
|
||||
uint64_t cycles = machine().time().as_ticks(MASTER_CLOCK);
|
||||
uint64_t cycles = machine().time().as_ticks(master_clock());
|
||||
uint32_t frame_cycles = (uint32_t)(cycles - m_frame_start_cycle);
|
||||
|
||||
if (m_last_cycles < frame_cycles)
|
||||
@ -214,67 +254,93 @@ uint32_t craft_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap,
|
||||
// MACHINE
|
||||
//**************************************************************************
|
||||
|
||||
static INPUT_PORTS_START( craft )
|
||||
static INPUT_PORTS_START( empty_input )
|
||||
INPUT_PORTS_END
|
||||
|
||||
void lft_state::machine_start()
|
||||
{
|
||||
save_item(NAME(m_ports));
|
||||
}
|
||||
|
||||
void lft_state::machine_reset()
|
||||
{
|
||||
memset(m_ports, 0, PORT_COUNT);
|
||||
}
|
||||
|
||||
void craft_state::machine_start()
|
||||
{
|
||||
lft_state::machine_start();
|
||||
|
||||
m_pixels = std::make_unique<uint8_t[]>(PIXELS_PER_FRAME);
|
||||
|
||||
save_item(NAME(m_last_cycles));
|
||||
save_item(NAME(m_frame_start_cycle));
|
||||
|
||||
save_item(NAME(m_port_b));
|
||||
save_item(NAME(m_port_c));
|
||||
save_item(NAME(m_port_d));
|
||||
|
||||
save_item(NAME(m_latched_color));
|
||||
save_pointer(NAME(m_pixels), PIXELS_PER_FRAME);
|
||||
}
|
||||
|
||||
void craft_state::machine_reset()
|
||||
{
|
||||
lft_state::machine_reset();
|
||||
|
||||
m_frame_start_cycle = 0;
|
||||
m_last_cycles = 0;
|
||||
|
||||
m_port_b = 0;
|
||||
m_port_c = 0;
|
||||
m_port_d = 0;
|
||||
|
||||
m_latched_color = 0;
|
||||
memset(&m_pixels[0], 0, PIXELS_PER_FRAME);
|
||||
}
|
||||
|
||||
void craft_state::craft(machine_config &config)
|
||||
void lft_state::base_config(machine_config &config)
|
||||
{
|
||||
/* basic machine hardware */
|
||||
ATMEGA88(config, m_maincpu, MASTER_CLOCK);
|
||||
m_maincpu->set_addrmap(AS_PROGRAM, &craft_state::craft_prg_map);
|
||||
m_maincpu->set_addrmap(AS_DATA, &craft_state::craft_data_map);
|
||||
m_maincpu->set_addrmap(AS_IO, &craft_state::craft_io_map);
|
||||
ATMEGA88(config, m_maincpu, master_clock());
|
||||
m_maincpu->set_addrmap(AS_PROGRAM, &lft_state::prg_map);
|
||||
m_maincpu->set_addrmap(AS_DATA, &lft_state::data_map);
|
||||
m_maincpu->set_addrmap(AS_IO, &lft_state::io_map);
|
||||
m_maincpu->set_eeprom_tag("eeprom");
|
||||
|
||||
/* video hardware */
|
||||
/* sound hardware */
|
||||
SPEAKER(config, "avr8").front_center();
|
||||
voltage_regulator_device &vref(VOLTAGE_REGULATOR(config, "vref", 0));
|
||||
vref.add_route(0, m_dac, 1.0, DAC_VREF_POS_INPUT);
|
||||
vref.add_route(0, m_dac, -1.0, DAC_VREF_NEG_INPUT);
|
||||
}
|
||||
|
||||
void craft_state::craft(machine_config &config)
|
||||
{
|
||||
base_config(config);
|
||||
|
||||
SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
|
||||
m_screen->set_raw(MASTER_CLOCK, 635, 47, 527, 525, 36, 516);
|
||||
m_screen->set_raw(master_clock(), 635, 47, 527, 525, 36, 516);
|
||||
m_screen->set_screen_update(FUNC(craft_state::screen_update));
|
||||
|
||||
PALETTE(config, m_palette, FUNC(craft_state::init_palette), 64);
|
||||
|
||||
/* sound hardware */
|
||||
SPEAKER(config, "avr8").front_center();
|
||||
DAC_6BIT_R2R(config, "dac", 0).add_route(0, "avr8", 0.25); // pd1/pd2/pd4/pd5/pd6/pd7 + 2k(x7) + 1k(x5)
|
||||
voltage_regulator_device &vref(VOLTAGE_REGULATOR(config, "vref", 0));
|
||||
vref.add_route(0, "dac", 1.0, DAC_VREF_POS_INPUT);
|
||||
vref.add_route(0, "dac", -1.0, DAC_VREF_NEG_INPUT);
|
||||
DAC_6BIT_R2R(config, m_dac, 0).add_route(0, "avr8", 0.25); // pd1/pd2/pd4/pd5/pd6/pd7 + 2k(x7) + 1k(x5)
|
||||
}
|
||||
|
||||
void powernin_state::powernin(machine_config &config)
|
||||
{
|
||||
base_config(config);
|
||||
|
||||
DAC_8BIT_R2R(config, m_dac, 0).add_route(0, "avr8", 0.9);
|
||||
}
|
||||
|
||||
ROM_START( craft )
|
||||
ROM_REGION( 0x2000, "maincpu", 0 ) /* Main program store */
|
||||
ROM_REGION( 0x2000, "maincpu", 0 )
|
||||
ROM_LOAD( "craft.bin", 0x0000, 0x2000, CRC(2e6f9ad2) SHA1(75e495bf18395d74289ca7ee2649622fc4010457) )
|
||||
ROM_REGION( 0x200, "eeprom", 0 ) /* on-die eeprom */
|
||||
ROM_REGION( 0x200, "eeprom", 0 )
|
||||
ROM_LOAD( "eeprom.raw", 0x0000, 0x0200, CRC(e18a2af9) SHA1(81fc6f2d391edfd3244870214fac37929af0ac0c) )
|
||||
ROM_END
|
||||
|
||||
/* YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME */
|
||||
CONS(2008, craft, 0, 0, craft, craft, craft_state, empty_init, "Linus Akesson", "Craft", MACHINE_IMPERFECT_GRAPHICS)
|
||||
ROM_START( powernin )
|
||||
ROM_REGION( 0x2000, "maincpu", 0 )
|
||||
ROM_LOAD( "powernin.bin", 0x0000, 0x2000, CRC(67458936) SHA1(26a86846a24dd974723a66bea6c22baf51c7bec9) )
|
||||
ROM_REGION( 0x200, "eeprom", 0 )
|
||||
ROM_LOAD( "eeprom.raw", 0x0000, 0x0200, CRC(bd7bc39f) SHA1(9d0ac37bb3ec8c95990fd37a962a17a95ce97aa0) )
|
||||
ROM_END
|
||||
|
||||
/* YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME */
|
||||
CONS(2008, craft, 0, 0, craft, empty_input, craft_state, empty_init, "Linus Åkesson", "Craft", MACHINE_IMPERFECT_GRAPHICS)
|
||||
CONS(2009, powernin, 0, 0, powernin, empty_input, powernin_state, empty_init, "Linus Åkesson", "Power Ninja Action Challenge", 0)
|
||||
|
@ -11263,6 +11263,7 @@ cpzodiacj //
|
||||
|
||||
@source:craft.cpp
|
||||
craft // Craft, by [lft]
|
||||
powernin // Power Ninja Action Challenge, by [lft]
|
||||
|
||||
@source:crazybal.cpp
|
||||
crazybal // EGS
|
||||
|
Loading…
Reference in New Issue
Block a user