summaryrefslogtreecommitdiffstatshomepage
path: root/src
diff options
context:
space:
mode:
author Miodrag Milanovic <mmicko@gmail.com>2013-12-30 07:21:37 +0000
committer Miodrag Milanovic <mmicko@gmail.com>2013-12-30 07:21:37 +0000
commita0d7e3ca1daf5133d584bfcb576e609e27352ea1 (patch)
treeb56c854221c413e9f8860b9b0e44da4c8b330e22 /src
parent0e95be33eea15f37217c2a3bf9579ab39273af05 (diff)
-AVR8 improvements: [Felipe Sanches]
- Added ELPM instructions - Added fuse bits macros - Added reset logic to decide initial program counter based on fuse bits configuration - Added initial support for ATMEGA1280 and ATMEGA2560 - Use register names in the disassembly of IN and OUT instructions (MESS) New driver : Replicator 1 [Felipe Sanches] (MESS) Replicator 1 driver: [Felipe Sanches] - status: no sound / not working - general skeleton. - basic memory mapping - shift-register interfacing from PORTC writes to the LCD device - avr8 fuses configuration
Diffstat (limited to 'src')
-rw-r--r--src/emu/cpu/avr8/avr8.c1224
-rw-r--r--src/emu/cpu/avr8/avr8.h381
-rw-r--r--src/emu/cpu/avr8/avr8dasm.c14
-rw-r--r--src/mess/drivers/craft.c10
-rw-r--r--src/mess/drivers/replicator.c682
-rw-r--r--src/mess/mess.lst3
-rw-r--r--src/mess/mess.mak4
-rw-r--r--src/targets/mess.lst3
8 files changed, 2137 insertions, 184 deletions
diff --git a/src/emu/cpu/avr8/avr8.c b/src/emu/cpu/avr8/avr8.c
index ecaf238c72d..05d31369a5e 100644
--- a/src/emu/cpu/avr8/avr8.c
+++ b/src/emu/cpu/avr8/avr8.c
@@ -9,9 +9,25 @@
the existing opcodes has been shown to wildly corrupt the video output in Craft, so one can assume that the
existing timing is 100% correct.
- Unimplemented opcodes: ELPM, SPM, SPM Z+, EIJMP, SLEEP, BREAK, WDR, EICALL, JMP, CALL
+ Unimplemented opcodes: SPM, SPM Z+, EIJMP, SLEEP, BREAK, WDR, EICALL, JMP, CALL
- Changelist -
+ 29 Dec. 2013 [Felipe Sanches]
+ - Added crude boilerplate code for Timer/Counter #4
+
+ 25 Dec. 2013 [Felipe Sanches]
+ - Updated AVR8_REGIDX_* enum based on ATMEGA640/1280/2560 datasheet
+
+ 24 Dec. 2013 [Felipe Sanches]
+ - update data memory mapping so that all 0x200 register addresses are accessible
+
+ 23 Dec. 2013 [Felipe Sanches]
+ - Added ELPM instructions
+ - Added fuse bits macros
+ - Added reset logic to decide initial program counter based on fuse bits configuration
+ - Added initial support for ATMEGA1280 and ATMEGA2560
+ - Use register names in the disassembly of IN and OUT instructions
+
23 Dec. 2012 [Sandro Ronco]
- Added CPSE, LD Z+, ST -Z/-Y/-X and ICALL opcodes
- Fixed Z flag in CPC, SBC and SBCI opcodes
@@ -109,6 +125,26 @@ enum
WGM02_FAST_PWM_CMP
};
+enum
+{
+ WGM4_NORMAL = 0,
+ WGM4_PWM_8_PC,
+ WGM4_PWM_9_PC,
+ WGM4_PWM_10_PC,
+ WGM4_CTC_OCR,
+ WGM4_FAST_PWM_8,
+ WGM4_FAST_PWM_9,
+ WGM4_FAST_PWM_10,
+ WGM4_PWM_PFC_ICR,
+ WGM4_PWM_PFC_OCR,
+ WGM4_PWM_PC_ICR,
+ WGM4_PWM_PC_OCR,
+ WGM4_CTC_ICR,
+ WGM4_RESERVED,
+ WGM4_FAST_PWM_ICR,
+ WGM4_FAST_PWM_OCR
+};
+
static const char avr8_reg_name[4] = { 'A', 'B', 'C', 'D' };
#define SREG_R(b) ((m_r[AVR8_REGIDX_SREG] & (1 << (b))) >> (b))
@@ -140,6 +176,8 @@ static const char avr8_reg_name[4] = { 'A', 'B', 'C', 'D' };
#define SPREG ((m_r[AVR8_REGIDX_SPH] << 8) | m_r[AVR8_REGIDX_SPL])
// I/O Defines
+#define AVR8_OCR1CH (m_r[AVR8_REGIDX_OCR1CH])
+#define AVR8_OCR1CL (m_r[AVR8_REGIDX_OCR1CL])
#define AVR8_OCR1BH (m_r[AVR8_REGIDX_OCR1BH])
#define AVR8_OCR1BL (m_r[AVR8_REGIDX_OCR1BL])
#define AVR8_OCR1AH (m_r[AVR8_REGIDX_OCR1AH])
@@ -271,6 +309,51 @@ static const char avr8_reg_name[4] = { 'A', 'B', 'C', 'D' };
#define AVR8_TIFR2_TOV2_SHIFT 0
#define AVR8_TIFR2_MASK (AVR8_TIFR2_TOV2_MASK | AVR8_TIFR2_OCF2B_MASK | AVR8_TIFR2_OCF2A_MASK)
+#define AVR8_TCCR4B (m_r[AVR8_REGIDX_TCCR4B])
+#define AVR8_TCCR4B_FOC4A_MASK 0x80
+#define AVR8_TCCR4B_FOC4A_SHIFT 7
+#define AVR8_TCCR4B_FOC4B_MASK 0x40
+#define AVR8_TCCR4B_FOC4B_SHIFT 6
+#define AVR8_TCCR4B_FOC4C_MASK 0x20
+#define AVR8_TCCR4B_FOC4C_SHIFT 5
+#define AVR8_TCCR4B_WGM4_32_MASK 0x18
+#define AVR8_TCCR4B_WGM4_32_SHIFT 3
+#define AVR8_TCCR4B_CS_MASK 0x07
+#define AVR8_TCCR4B_CS_SHIFT 0
+#define AVR8_TIMER4_CLOCK_SELECT ((AVR8_TCCR4B & AVR8_TCCR4B_CS_MASK) >> AVR8_TCCR4B_CS_SHIFT)
+
+#define AVR8_TCCR4A (m_r[AVR8_REGIDX_TCCR4A])
+#define AVR8_TCCR4A_COM4A_MASK 0xc0
+#define AVR8_TCCR4A_COM4A_SHIFT 6
+#define AVR8_TCCR4A_COM4B_MASK 0x30
+#define AVR8_TCCR4A_COM4B_SHIFT 4
+#define AVR8_TCCR4A_WGM4_10_MASK 0x03
+#define AVR8_TCCR4A_WGM4_10_SHIFT 0
+#define AVR8_TCCR4A_COM4A ((AVR8_TCCR4A & AVR8_TCCR4A_COM4A_MASK) >> AVR8_TCCR4A_COM4A_SHIFT)
+#define AVR8_TCCR4A_COM4B ((AVR8_TCCR4A & AVR8_TCCR4A_COM4B_MASK) >> AVR8_TCCR4A_COM4B_SHIFT)
+#define AVR8_TCCR4A_WGM2_10 (AVR8_TCCR4A & AVR8_TCCR4A_WGM2_10_MASK)
+
+#define AVR8_WGM4_32 ((AVR8_TCCR4B & AVR8_TCCR4B_WGM4_32_MASK) >> AVR8_TCCR4B_WGM4_32_SHIFT)
+#define AVR8_WGM4_10 ((AVR8_TCCR4A & AVR8_TCCR4A_WGM4_10_MASK) >> AVR8_TCCR4A_WGM4_10_SHIFT)
+#define AVR8_WGM4 ((AVR8_WGM4_32 << 2) | AVR8_WGM4_10)
+
+#define AVR8_TIMSK4 (m_r[AVR8_REGIDX_TIMSK4])
+#define AVR8_TIMSK4_OCIE4B_MASK 0x04
+#define AVR8_TIMSK4_OCIE4A_MASK 0x02
+#define AVR8_TIMSK4_TOIE4_MASK 0x01
+#define AVR8_TIMSK4_OCIE4B ((AVR8_TIMSK4 & AVR8_TIMSK4_OCIE4B_MASK) >> 2)
+#define AVR8_TIMSK4_OCIE4A ((AVR8_TIMSK4 & AVR8_TIMSK4_OCIE4A_MASK) >> 1)
+#define AVR8_TIMSK4_TOIE4 (AVR8_TIMSK4 & AVR8_TIMSK4_TOIE4_MASK)
+
+#define AVR8_TIFR4 (m_r[AVR8_REGIDX_TIFR4])
+#define AVR8_TIFR4_OCF4B_MASK 0x04
+#define AVR8_TIFR4_OCF4B_SHIFT 2
+#define AVR8_TIFR4_OCF4A_MASK 0x02
+#define AVR8_TIFR4_OCF4A_SHIFT 1
+#define AVR8_TIFR4_TOV4_MASK 0x01
+#define AVR8_TIFR4_TOV4_SHIFT 0
+#define AVR8_TIFR4_MASK (AVR8_TIFR4_TOV4_MASK | AVR8_TIFR4_OCF4B_MASK | AVR8_TIFR4_OCF4A_MASK)
+
#define AVR8_OCR0A m_r[AVR8_REGIDX_OCR0A]
#define AVR8_OCR0B m_r[AVR8_REGIDX_OCR0B]
#define AVR8_TCNT0 m_r[AVR8_REGIDX_TCNT0]
@@ -278,6 +361,7 @@ static const char avr8_reg_name[4] = { 'A', 'B', 'C', 'D' };
#define AVR8_OCR1A ((AVR8_OCR1AH << 8) | AVR8_OCR1AL)
#define AVR8_OCR1B ((AVR8_OCR1BH << 8) | AVR8_OCR1BL)
+#define AVR8_OCR1C ((AVR8_OCR1CH << 8) | AVR8_OCR1CL)
#define AVR8_ICR1 ((AVR8_ICR1H << 8) | AVR8_ICR1L)
#define AVR8_TCNT1 ((AVR8_TCNT1H << 8) | AVR8_TCNT1L)
#define AVR8_WGM1 (((AVR8_TCCR1B & 0x18) >> 1) | (AVR8_TCCR1A & 0x03))
@@ -288,6 +372,21 @@ static const char avr8_reg_name[4] = { 'A', 'B', 'C', 'D' };
#define AVR8_TCNT2 m_r[AVR8_REGIDX_TCNT2]
#define AVR8_WGM2 (((AVR8_TCCR2B & 0x08) >> 1) | (AVR8_TCCR2A & 0x03))
+#define AVR8_TCNT3L m_r[AVR8_REGIDX_TCNT3L]
+#define AVR8_TCNT3H m_r[AVR8_REGIDX_TCNT3H]
+
+#define AVR8_ICR4 ((AVR8_ICR4H << 8) | AVR8_ICR4L)
+#define AVR8_ICR4H (m_r[AVR8_REGIDX_ICR4H])
+#define AVR8_ICR4L (m_r[AVR8_REGIDX_ICR4L])
+#define AVR8_OCR4AH m_r[AVR8_REGIDX_OCR4AH]
+#define AVR8_OCR4AL m_r[AVR8_REGIDX_OCR4AL]
+#define AVR8_OCR4A ((AVR8_OCR4AH << 8) | AVR8_OCR4AL)
+#define AVR8_OCR4B m_r[AVR8_REGIDX_OCR4B]
+#define AVR8_TCNT4 m_r[AVR8_REGIDX_TCNT4]
+
+#define AVR8_TCNT4L m_r[AVR8_REGIDX_TCNT4L]
+#define AVR8_TCNT4H m_r[AVR8_REGIDX_TCNT4H]
+
#define AVR8_GTCCR_PSRASY_MASK 0x02
#define AVR8_GTCCR_PSRASY_SHIFT 1
@@ -313,21 +412,35 @@ static const char avr8_reg_name[4] = { 'A', 'B', 'C', 'D' };
const device_type ATMEGA88 = &device_creator<atmega88_device>;
const device_type ATMEGA644 = &device_creator<atmega644_device>;
+const device_type ATMEGA1280 = &device_creator<atmega1280_device>;
+const device_type ATMEGA2560 = &device_creator<atmega2560_device>;
//**************************************************************************
// INTERNAL ADDRESS MAP
//**************************************************************************
-static ADDRESS_MAP_START( avr8_internal_map, AS_DATA, 8, avr8_device )
+static ADDRESS_MAP_START( atmega88_internal_map, AS_DATA, 8, atmega88_device )
AM_RANGE(0x0000, 0x00ff) AM_READWRITE( regs_r, regs_w )
ADDRESS_MAP_END
+static ADDRESS_MAP_START( atmega644_internal_map, AS_DATA, 8, atmega644_device )
+ AM_RANGE(0x0000, 0x00ff) AM_READWRITE( regs_r, regs_w )
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START( atmega1280_internal_map, AS_DATA, 8, atmega1280_device )
+ AM_RANGE(0x0000, 0x01ff) AM_READWRITE( regs_r, regs_w )
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START( atmega2560_internal_map, AS_DATA, 8, atmega2560_device )
+ AM_RANGE(0x0000, 0x01ff) AM_READWRITE( regs_r, regs_w )
+ADDRESS_MAP_END
+
//-------------------------------------------------
// atmega88_device - constructor
//-------------------------------------------------
atmega88_device::atmega88_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
- : avr8_device(mconfig, "ATMEGA88", tag, owner, clock, ATMEGA88, 0x0fff, ADDRESS_MAP_NAME(avr8_internal_map), "atmega88", __FILE__)
+ : avr8_device(mconfig, "ATMEGA88", tag, owner, clock, ATMEGA88, 0x0fff, ADDRESS_MAP_NAME(atmega88_internal_map), CPU_TYPE_ATMEGA88, "atmega88", __FILE__)
{
}
@@ -336,7 +449,25 @@ atmega88_device::atmega88_device(const machine_config &mconfig, const char *tag,
//-------------------------------------------------
atmega644_device::atmega644_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
- : avr8_device(mconfig, "ATMEGA644", tag, owner, clock, ATMEGA644, 0xffff, ADDRESS_MAP_NAME(avr8_internal_map), "atmega644", __FILE__)
+ : avr8_device(mconfig, "ATMEGA644", tag, owner, clock, ATMEGA644, 0xffff, ADDRESS_MAP_NAME(atmega644_internal_map), CPU_TYPE_ATMEGA644, "atmega644", __FILE__)
+{
+}
+
+//-------------------------------------------------
+// atmega1280_device - constructor
+//-------------------------------------------------
+
+atmega1280_device::atmega1280_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : avr8_device(mconfig, "ATMEGA1280", tag, owner, clock, ATMEGA1280, 0x1ffff, ADDRESS_MAP_NAME(atmega1280_internal_map), CPU_TYPE_ATMEGA1280, "atmega1280", __FILE__)
+{
+}
+
+//-------------------------------------------------
+// atmega2560_device - constructor
+//-------------------------------------------------
+
+atmega2560_device::atmega2560_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : avr8_device(mconfig, "ATMEGA2560", tag, owner, clock, ATMEGA2560, 0x3ffff, ADDRESS_MAP_NAME(atmega2560_internal_map), CPU_TYPE_ATMEGA2560, "atmega2560", __FILE__)
{
}
@@ -344,14 +475,19 @@ atmega644_device::atmega644_device(const machine_config &mconfig, const char *ta
// avr8_device - constructor
//-------------------------------------------------
-avr8_device::avr8_device(const machine_config &mconfig, const char *name, const char *tag, device_t *owner, UINT32 clock, const device_type type, UINT32 addr_mask, address_map_constructor internal_map, const char *shortname, const char *source)
+avr8_device::avr8_device(const machine_config &mconfig, const char *name, const char *tag, device_t *owner, UINT32 clock, const device_type type, UINT32 addr_mask, address_map_constructor internal_map, UINT8 cpu_type, const char *shortname, const char *source)
: cpu_device(mconfig, type, name, tag, owner, clock, shortname, source),
+ m_shifted_pc(0),
m_program_config("program", ENDIANNESS_LITTLE, 8, 22),
m_data_config("data", ENDIANNESS_LITTLE, 8, 16, 0, internal_map),
- m_io_config("io", ENDIANNESS_LITTLE, 8, 2),
+ m_io_config("io", ENDIANNESS_LITTLE, 8, 4),
m_eeprom(NULL),
+ m_cpu_type(cpu_type),
+ m_lfuses(0x62),
+ m_hfuses(0x99),
+ m_efuses(0xFF),
+ m_lock_bits(0xFF),
m_pc(0),
- m_shifted_pc(0),
m_timer0_top(0),
m_timer0_increment(1),
m_timer0_prescale(0),
@@ -364,6 +500,10 @@ avr8_device::avr8_device(const machine_config &mconfig, const char *name, const
m_timer2_increment(1),
m_timer2_prescale(0),
m_timer2_prescale_count(0),
+ m_timer4_top(0),
+ m_timer4_increment(1),
+ m_timer4_prescale(0),
+ m_timer4_prescale_count(0),
m_spi_active(false),
m_spi_prescale(0),
m_spi_prescale_count(0),
@@ -387,6 +527,41 @@ void avr8_device::static_set_config(device_t &device, const avr8_config &config)
static_cast<avr8_config &>(avr8) = config;
}
+//-------------------------------------------------
+// static_set_low_fuses
+//-------------------------------------------------
+
+void avr8_device::set_low_fuses(const UINT8 byte)
+{
+ m_lfuses = byte;
+}
+
+//-------------------------------------------------
+// static_set_high_fuses
+//-------------------------------------------------
+
+void avr8_device::set_high_fuses(const UINT8 byte)
+{
+ m_hfuses = byte;
+}
+
+//-------------------------------------------------
+// static_set_extended_fuses
+//-------------------------------------------------
+
+void avr8_device::set_extended_fuses(const UINT8 byte)
+{
+ m_efuses = byte;
+}
+
+//-------------------------------------------------
+// static_set_lock_bits
+//-------------------------------------------------
+
+void avr8_device::set_lock_bits(const UINT8 byte)
+{
+ m_lock_bits = byte;
+}
//-------------------------------------------------
// unimplemented_opcode - bail on unspuported
@@ -395,7 +570,8 @@ void avr8_device::static_set_config(device_t &device, const avr8_config &config)
void avr8_device::unimplemented_opcode(UINT32 op)
{
- fatalerror("AVR8: unknown opcode (%08x) at %08x\n", op, m_pc);
+// debugger_break(machine());
+ fatalerror("AVR8: unknown opcode (%08x) at %08x\n", op, m_shifted_pc);
}
@@ -443,7 +619,9 @@ void avr8_device::device_start()
state_add(STATE_GENPC, "GENPC", m_shifted_pc).noshow();
state_add(STATE_GENFLAGS, "GENFLAGS", m_r[AVR8_REGIDX_SREG]).callimport().callexport().formatstr("%8s").noshow();
state_add(AVR8_SREG, "STATUS", m_r[AVR8_REGIDX_SREG]).mask(0xff);
- state_add(AVR8_PC, "PC", m_shifted_pc).mask(0xffff);
+ state_add(AVR8_PC, "PC", m_shifted_pc).mask(m_addr_mask);
+ state_add(AVR8_SPH, "SPH", m_r[AVR8_REGIDX_SPH]).mask(0xff);
+ state_add(AVR8_SPL, "SPL", m_r[AVR8_REGIDX_SPL]).mask(0xff);
state_add(AVR8_R0, "R0", m_r[ 0]).mask(0xff);
state_add(AVR8_R1, "R1", m_r[ 1]).mask(0xff);
state_add(AVR8_R2, "R2", m_r[ 2]).mask(0xff);
@@ -492,6 +670,10 @@ void avr8_device::device_start()
save_item(NAME(m_timer2_increment));
save_item(NAME(m_timer2_prescale));
save_item(NAME(m_timer2_prescale_count));
+ save_item(NAME(m_timer4_top));
+ save_item(NAME(m_timer4_increment));
+ save_item(NAME(m_timer4_prescale));
+ save_item(NAME(m_timer4_prescale_count));
save_item(NAME(m_addr_mask));
save_item(NAME(m_interrupt_pending));
save_item(NAME(m_icount));
@@ -509,10 +691,31 @@ void avr8_device::device_start()
void avr8_device::device_reset()
{
+ logerror("AVR low fuse bits: 0x%02X\n", m_lfuses);
+ logerror("AVR high fuse bits: 0x%02X\n", m_hfuses);
+ logerror("AVR extended fuse bits: 0x%02X\n", m_efuses);
+ logerror("AVR lock bits: 0x%02X\n", m_lock_bits);
+
+ switch ((m_hfuses & (BOOTSZ1|BOOTSZ0)) >> 1){
+ case 0: m_boot_size = 4096; break;
+ case 1: m_boot_size = 2048; break;
+ case 2: m_boot_size = 1024; break;
+ case 3: m_boot_size = 512; break;
+ default: break;
+ }
+
+ if (m_hfuses & BOOTRST){
+ m_shifted_pc = 0x0000;
+ logerror("Booting AVR core from address 0x0000\n");
+ } else {
+ m_shifted_pc = (m_addr_mask + 1) - 2*m_boot_size;
+ logerror("AVR Boot loader section size: %d words\n", m_boot_size);
+ }
+
m_r[AVR8_REGIDX_SPL] = 0;
m_r[AVR8_REGIDX_SPH] = 0;
- for (int i = 0; i < 256; i++)
+ for (int i = 0; i < 0x200; i++)
{
m_r[i] = 0;
}
@@ -536,17 +739,30 @@ void avr8_device::device_reset()
m_timer2_prescale = 0;
m_timer2_prescale_count = 0;
+ m_timer4_top = 0;
+ m_timer4_increment = 1;
+ m_timer4_prescale = 0;
+ m_timer4_prescale_count = 0;
+
AVR8_TIMSK1 = 0;
AVR8_OCR1AH = 0;
AVR8_OCR1AL = 0;
AVR8_OCR1BH = 0;
AVR8_OCR1BL = 0;
+ AVR8_OCR1CH = 0;
+ AVR8_OCR1CL = 0;
AVR8_ICR1H = 0;
AVR8_ICR1L = 0;
AVR8_TCNT1H = 0;
AVR8_TCNT1L = 0;
AVR8_TCNT2 = 0;
+ AVR8_TIMSK4 = 0;
+ AVR8_TCNT4H = 0;
+ AVR8_ICR4H = 0;
+ AVR8_ICR4L = 0;
+ AVR8_TCNT4L = 0;
+
m_interrupt_pending = false;
m_elapsed_cycles = 0;
@@ -751,6 +967,38 @@ void atmega644_device::update_interrupt(int source)
}
}
+//TODO: review this!
+void atmega1280_device::update_interrupt(int source)
+{
+ CInterruptCondition condition = s_mega644_int_conditions[source];
+
+ int intstate = (m_r[condition.m_regindex] & condition.m_regmask) ? 1 : 0;
+ intstate = (m_r[condition.m_intreg] & condition.m_intmask) ? intstate : 0;
+
+ set_irq_line(condition.m_intindex << 1, intstate);
+
+ if (intstate)
+ {
+ m_r[condition.m_regindex] &= ~condition.m_regmask;
+ }
+}
+
+//TODO: review this!
+void atmega2560_device::update_interrupt(int source)
+{
+ CInterruptCondition condition = s_mega644_int_conditions[source];
+
+ int intstate = (m_r[condition.m_regindex] & condition.m_regmask) ? 1 : 0;
+ intstate = (m_r[condition.m_intreg] & condition.m_intmask) ? intstate : 0;
+
+ set_irq_line(condition.m_intindex << 1, intstate);
+
+ if (intstate)
+ {
+ m_r[condition.m_regindex] &= ~condition.m_regmask;
+ }
+}
+
//**************************************************************************
// REGISTER HANDLING
@@ -768,7 +1016,7 @@ void avr8_device::timer_tick(int cycles)
{
UINT8 out_bit = (m_r[AVR8_REGIDX_SPDR] & (1 << m_spi_prescale_countdown)) >> m_spi_prescale_countdown;
m_spi_prescale_countdown--;
- m_io->write_byte(0x01, (m_r[AVR8_REGIDX_PORTB] &~ AVR8_PORTB_MOSI) | (out_bit ? AVR8_PORTB_MOSI : 0));
+ m_io->write_byte(AVR8_IO_PORTB, (m_r[AVR8_REGIDX_PORTB] &~ AVR8_PORTB_MOSI) | (out_bit ? AVR8_PORTB_MOSI : 0));
m_r[AVR8_REGIDX_PORTB] = (m_r[AVR8_REGIDX_PORTB] &~ AVR8_PORTB_MOSI) | (out_bit ? AVR8_PORTB_MOSI : 0);
m_spi_prescale_count -= m_spi_prescale;
}
@@ -803,6 +1051,17 @@ void avr8_device::timer_tick(int cycles)
m_timer2_prescale_count -= m_timer2_prescale;
}
}
+
+ if (m_timer4_prescale != 0)
+ {
+ m_timer4_prescale_count++;
+ if (m_timer4_prescale_count == m_timer4_prescale)
+ {
+ timer4_tick();
+ m_timer4_prescale_count -= m_timer4_prescale;
+ }
+ }
+
}
}
@@ -1476,6 +1735,264 @@ void avr8_device::update_ocr2(UINT8 newval, UINT8 reg)
// Nothing needs to be done? All handled in timer callback
}
+/************************************************************************************************/
+
+void avr8_device::timer4_tick()
+{
+ /* TODO: Handle comparison, setting OC1x pins, detection of BOTTOM and TOP */
+
+ UINT16 count = (m_r[AVR8_REGIDX_TCNT4H] << 8) | m_r[AVR8_REGIDX_TCNT4L];
+
+ // Cache things in array form to avoid a compare+branch inside a potentially high-frequency timer
+ //UINT8 compare_mode[2] = { (m_r[AVR8_REGIDX_TCCR1A] & AVR8_TCCR1A_COM1A_MASK) >> AVR8_TCCR1A_COM1A_SHIFT,
+ //(m_r[AVR8_REGIDX_TCCR1A] & AVR8_TCCR1A_COM1B_MASK) >> AVR8_TCCR1A_COM1B_SHIFT };
+ UINT16 ocr4[2] = { (m_r[AVR8_REGIDX_OCR4AH] << 8) | m_r[AVR8_REGIDX_OCR4AL],
+ (m_r[AVR8_REGIDX_OCR4BH] << 8) | m_r[AVR8_REGIDX_OCR4BL] };
+//TODO UINT8 ocf4[2] = { (1 << AVR8_TIFR4_OCF4A_SHIFT), (1 << AVR8_TIFR4_OCF4B_SHIFT) };
+//TODO UINT8 int4[2] = { AVR8_INTIDX_OCF4A, AVR8_INTIDX_OCF4B };
+ INT32 increment = m_timer4_increment;
+
+ for(INT32 reg = AVR8_REG_A; reg <= AVR8_REG_B; reg++)
+ {
+ switch(AVR8_WGM4)
+ {
+ case WGM4_FAST_PWM_8:
+ case WGM4_FAST_PWM_9:
+ case WGM4_FAST_PWM_10:
+ if (count == m_timer4_top){
+ //printf("[T4] tick WGM4_FAST_PWM_8: %d\n", count);
+ count=0;
+ }
+ break;
+
+ case WGM4_CTC_OCR:
+ //printf("[T4] tick WGM4_CTC_OCR: %d\n", count);
+ if (count == 0xffff)
+ {
+ m_r[AVR8_REGIDX_TIFR4] |= AVR8_TIFR4_TOV4_MASK;
+ update_interrupt(AVR8_INTIDX_TOV4);
+ count = 0;
+ increment = 0;
+ }
+
+ if (count == ocr4[reg])
+ {
+ if (reg == 0)
+ {
+ count = 0;
+ increment = 0;
+ }
+//TODO m_r[AVR8_REGIDX_TIFR4] |= ocf4[reg];
+//TODO update_interrupt(int4[reg]);
+ }
+ else if (count == 0)
+ {
+ if (reg == 0)
+ {
+//TODO m_r[AVR8_REGIDX_TIFR4] &= ~AVR8_TIFR4_TOV4_MASK;
+//TODO update_interrupt(AVR8_INTIDX_TOV4);
+ }
+
+//TODO m_r[AVR8_REGIDX_TIFR4] &= ~ocf4[reg];
+//TODO update_interrupt(int4[reg]);
+ }
+ break;
+
+ case WGM1_FAST_PWM_OCR:
+ if(count == ocr4[reg])
+ {
+ if (reg == 0)
+ {
+//TODO m_r[AVR8_REGIDX_TIFR4] |= AVR8_TIFR4_TOV4_MASK;
+//TODO update_interrupt(AVR8_INTIDX_TOV4);
+ count = 0;
+ increment = 0;
+ }
+
+//TODO m_r[AVR8_REGIDX_TIFR4] |= ocf4[reg];
+//TODO update_interrupt(int4[reg]);
+ }
+ else if(count == 0)
+ {
+ if (reg == 0)
+ {
+//TODO m_r[AVR8_REGIDX_TIFR4] &= ~AVR8_TIFR4_TOV4_MASK;
+//TODO update_interrupt(AVR8_INTIDX_TOV4);
+ }
+
+//TODO m_r[AVR8_REGIDX_TIFR4] &= ~ocf4[reg];
+//TODO update_interrupt(int4[reg]);
+ }
+ break;
+
+ default:
+// printf("[T4] tick Unknown waveform generation mode: %d\n", count);
+
+ verboselog(m_pc, 0, "update_timer4_compare_mode: Unknown waveform generation mode: %02x\n", wgm4);
+ break;
+ }
+ /*
+ switch(compare_mode[reg])
+ {
+ case 0:
+ //verboselog(m_pc, 0, "update_timer4_compare_mode: Normal port operation (OC1 disconnected)\n");
+ break;
+
+ case 1:
+ case 2:
+ // TODO
+ break;
+
+ case 3:
+ break;
+ }
+ */
+ }
+
+ count += increment;
+ m_r[AVR8_REGIDX_TCNT4H] = (count >> 8) & 0xff;
+ m_r[AVR8_REGIDX_TCNT4L] = count & 0xff;
+}
+
+void avr8_device::update_timer4_clock_source()
+{
+ debugger_break(machine());
+ switch(AVR8_TIMER4_CLOCK_SELECT)
+ {
+ case 0: // Counter stopped
+ m_timer4_prescale = 0;
+ //printf("[T4]: Counter stopped\n");
+ break;
+ case 1: // Clk/1; no prescaling
+ m_timer4_prescale = 1;
+ //printf("[T4]: prescale = 1\n");
+ break;
+ case 2: // Clk/8
+ m_timer4_prescale = 8;
+ //printf("[T4]: prescale = 8\n");
+ break;
+ case 3: // Clk/64
+ m_timer4_prescale = 64;
+ //printf("[T4]: prescale = 64\n");
+ break;
+ case 4: // Clk/256
+ m_timer4_prescale = 256;
+ //printf("[T4]: prescale = 256\n");
+ break;
+ case 5: // Clk/1024
+ m_timer4_prescale = 1024;
+ //printf("[T4]: prescale = 1024\n");
+ break;
+ case 6: // T0 trigger, falling edge
+ case 7: // T0 trigger, rising edge
+ //printf("[T4]: update_timer4_clock_source: T0 Trigger mode not implemented yet\n");
+ m_timer4_prescale = 0;
+ verboselog(m_pc, 0, "update_timer4_clock_source: T0 Trigger mode not implemented yet\n");
+ break;
+ }
+
+ if (m_timer4_prescale_count > m_timer4_prescale)
+ {
+ m_timer4_prescale_count = m_timer4_prescale - 1;
+ }
+}
+
+void avr8_device::update_timer4_waveform_gen_mode()
+{
+ //printf("[T4] AVR8_WGM4 = %d\n", AVR8_WGM4);
+
+ switch(AVR8_WGM4)
+ {
+ case WGM4_NORMAL:
+ m_timer4_top = 0xffff;
+ break;
+
+ case WGM4_PWM_8_PC:
+ case WGM4_FAST_PWM_8:
+ m_timer4_top = 0x00ff;
+ break;
+
+ case WGM4_PWM_9_PC:
+ case WGM4_FAST_PWM_9:
+ m_timer4_top = 0x01ff;
+ break;
+
+ case WGM4_PWM_10_PC:
+ case WGM4_FAST_PWM_10:
+ m_timer4_top = 0x03ff;
+ break;
+
+ case WGM4_PWM_PFC_ICR:
+ case WGM4_PWM_PC_ICR:
+ case WGM4_CTC_ICR:
+ case WGM4_FAST_PWM_ICR:
+ m_timer4_top = AVR8_ICR4;
+ break;
+
+ case WGM4_PWM_PFC_OCR:
+ case WGM4_PWM_PC_OCR:
+ case WGM4_CTC_OCR:
+ case WGM4_FAST_PWM_OCR:
+ m_timer4_top = AVR8_OCR4A;
+ break;
+
+ default:
+ m_timer4_top = 0;
+ verboselog(m_pc, 0, "update_timer4_waveform_gen_mode: Unsupported waveform generation type: %d\n", AVR8_WGM4);
+ break;
+ }
+}
+
+
+void avr8_device::changed_tccr4a(UINT8 data)
+{
+ UINT8 oldtccr = AVR8_TCCR4A;
+ UINT8 newtccr = data;
+ UINT8 changed = newtccr ^ oldtccr;
+
+ AVR8_TCCR4A = data;
+
+ if(changed & AVR8_TCCR4A_WGM4_10_MASK)
+ {
+ // TODO
+ update_timer4_waveform_gen_mode();
+ }
+}
+
+void avr8_device::changed_tccr4b(UINT8 data)
+{
+ UINT8 oldtccr = AVR8_TCCR4B;
+ UINT8 newtccr = data;
+ UINT8 changed = newtccr ^ oldtccr;
+
+ AVR8_TCCR4B = data;
+
+ if(changed & AVR8_TCCR4B_FOC4A_MASK)
+ {
+ // TODO
+// timer4_force_output_compare(AVR8_REG_A);
+ }
+
+ if(changed & AVR8_TCCR4B_FOC4B_MASK)
+ {
+ // TODO
+// timer4_force_output_compare(AVR8_REG_B);
+ }
+
+ if(changed & AVR8_TCCR4B_WGM4_32_MASK)
+ {
+ update_timer4_waveform_gen_mode();
+ }
+
+ if(changed & AVR8_TCCR4B_CS_MASK)
+ {
+ update_timer4_clock_source();
+ }
+}
+
+/************************************************************************************************/
+
+
/****************/
/* SPI Handling */
/****************/
@@ -1578,6 +2095,8 @@ void avr8_device::change_spsr(UINT8 data)
WRITE8_MEMBER( avr8_device::regs_w )
{
+ //printf("<<< WRITE offset [%04x]=%02x >>>\n", offset, data);
+
switch( offset )
{
case AVR8_REGIDX_R0:
@@ -1615,6 +2134,74 @@ WRITE8_MEMBER( avr8_device::regs_w )
m_r[offset] = data;
break;
+ case AVR8_REGIDX_PORTA:
+ m_io->write_byte(AVR8_IO_PORTA, data);
+ m_r[AVR8_REGIDX_PORTA] = data;
+ break;
+
+ case AVR8_REGIDX_PORTB:
+ m_io->write_byte(AVR8_IO_PORTB, data);
+ m_r[AVR8_REGIDX_PORTB] = data;
+ break;
+
+ case AVR8_REGIDX_PORTC:
+ m_io->write_byte(AVR8_IO_PORTC, data);
+ m_r[AVR8_REGIDX_PORTC] = data;
+ break;
+
+ case AVR8_REGIDX_PORTD:
+ m_io->write_byte(AVR8_IO_PORTD, data);
+ m_r[AVR8_REGIDX_PORTD] = data;
+ break;
+
+ case AVR8_REGIDX_PORTE:
+ m_io->write_byte(AVR8_IO_PORTE, data);
+ m_r[AVR8_REGIDX_PORTE] = data;
+ break;
+
+ case AVR8_REGIDX_PORTF:
+ m_io->write_byte(AVR8_IO_PORTF, data);
+ m_r[AVR8_REGIDX_PORTF] = data;
+ break;
+
+ case AVR8_REGIDX_PORTG:
+ m_io->write_byte(AVR8_IO_PORTG, data);
+ m_r[AVR8_REGIDX_PORTG] = data;
+ break;
+
+ case AVR8_REGIDX_PORTH:
+ m_io->write_byte(AVR8_IO_PORTH, data);
+ m_r[AVR8_REGIDX_PORTH] = data;
+ break;
+
+ case AVR8_REGIDX_PORTJ:
+ m_io->write_byte(AVR8_IO_PORTJ, data);
+ m_r[AVR8_REGIDX_PORTJ] = data;
+ break;
+
+ case AVR8_REGIDX_PORTK:
+ m_io->write_byte(AVR8_IO_PORTK, data);
+ m_r[AVR8_REGIDX_PORTK] = data;
+ break;
+
+ case AVR8_REGIDX_PORTL:
+ m_io->write_byte(AVR8_IO_PORTL, data);
+ m_r[AVR8_REGIDX_PORTL] = data;
+ break;
+
+ case AVR8_REGIDX_DDRA:
+ case AVR8_REGIDX_DDRB:
+ case AVR8_REGIDX_DDRC:
+ case AVR8_REGIDX_DDRD:
+ case AVR8_REGIDX_EEARL:
+ case AVR8_REGIDX_EEARH:
+ case AVR8_REGIDX_SREG:
+ case AVR8_REGIDX_RAMPZ:
+ case AVR8_REGIDX_SPH:
+ case AVR8_REGIDX_SPL:
+ m_r[offset] = data;
+ break;
+
case AVR8_REGIDX_TCCR0B:
verboselog(m_pc, 0, "AVR8: TCCR0B = %02x\n", data );
changed_tccr0b(data);
@@ -1635,14 +2222,6 @@ WRITE8_MEMBER( avr8_device::regs_w )
update_ocr0(AVR8_OCR0B, AVR8_REG_B);
break;
- case AVR8_REGIDX_TIMSK0:
- verboselog(m_pc, 0, "AVR8: TIMSK0 = %02x\n", data );
- m_r[AVR8_REGIDX_TIMSK0] = data;
- update_interrupt(AVR8_INTIDX_OCF0A);
- update_interrupt(AVR8_INTIDX_OCF0B);
- update_interrupt(AVR8_INTIDX_TOV0);
- break;
-
case AVR8_REGIDX_TIFR0:
verboselog(m_pc, 0, "AVR8: TIFR0 = %02x\n", data );
m_r[AVR8_REGIDX_TIFR0] &= ~(data & AVR8_TIFR0_MASK);
@@ -1655,34 +2234,128 @@ WRITE8_MEMBER( avr8_device::regs_w )
AVR8_TCNT0 = data;
break;
- case AVR8_REGIDX_TCCR1B:
- verboselog(m_pc, 0, "AVR8: TCCR1B = %02x\n", data );
- changed_tccr1b(data);
+ case AVR8_REGIDX_TIFR1:
+ verboselog(m_pc, 0, "AVR8: TIFR1 = %02x\n", data );
+ m_r[AVR8_REGIDX_TIFR1] &= ~(data & AVR8_TIFR1_MASK);
+ update_interrupt(AVR8_INTIDX_ICF1);
+ update_interrupt(AVR8_INTIDX_OCF1A);
+ update_interrupt(AVR8_INTIDX_OCF1B);
+ update_interrupt(AVR8_INTIDX_TOV1);
break;
- case AVR8_REGIDX_TCCR1A:
- verboselog(m_pc, 0, "AVR8: TCCR1A = %02x\n", data );
- changed_tccr1a(data);
+ case AVR8_REGIDX_TIFR2:
+ verboselog(m_pc, 0, "AVR8: TIFR2 = %02x\n", data );
+ m_r[AVR8_REGIDX_TIFR2] &= ~(data & AVR8_TIFR2_MASK);
+ update_interrupt(AVR8_INTIDX_OCF2A);
+ update_interrupt(AVR8_INTIDX_OCF2B);
+ update_interrupt(AVR8_INTIDX_TOV2);
break;
- case AVR8_REGIDX_OCR1BH:
- verboselog(m_pc, 0, "AVR8: OCR1BH = %02x\n", data );
- update_ocr1((AVR8_OCR1B & 0x00ff) | (data << 8), AVR8_REG_B);
+ case AVR8_REGIDX_GTCCR:
+ if (data & AVR8_GTCCR_PSRASY_MASK)
+ {
+ data &= ~AVR8_GTCCR_PSRASY_MASK;
+ m_timer2_prescale_count = 0;
+ }
break;
- case AVR8_REGIDX_OCR1BL:
- verboselog(m_pc, 0, "AVR8: OCR1BL = %02x\n", data );
- update_ocr1((AVR8_OCR1B & 0xff00) | data, AVR8_REG_B);
+ case AVR8_REGIDX_EECR:
+ if (data & AVR8_EECR_EERE)
+ {
+ UINT16 addr = (m_r[AVR8_REGIDX_EEARH] & AVR8_EEARH_MASK) << 8;
+ addr |= m_r[AVR8_REGIDX_EEARL];
+ m_r[AVR8_REGIDX_EEDR] = m_eeprom[addr];
+ }
break;
- case AVR8_REGIDX_OCR1AH:
- verboselog(m_pc, 0, "AVR8: OCR1AH = %02x\n", data );
- update_ocr1((AVR8_OCR1A & 0x00ff) | (data << 8), AVR8_REG_A);
+ case AVR8_REGIDX_GPIOR0:
+ verboselog(m_pc, 1, "AVR8: GPIOR0 Write: %02x\n", data);
+ m_r[AVR8_REGIDX_GPIOR0] = data;
break;
- case AVR8_REGIDX_OCR1AL:
- verboselog(m_pc, 0, "AVR8: OCR1AL = %02x\n", data );
- update_ocr1((AVR8_OCR1A & 0xff00) | data, AVR8_REG_A);
+ case AVR8_REGIDX_GPIOR1:
+ case AVR8_REGIDX_GPIOR2:
+ m_r[offset] = data;
+ break;
+
+ case AVR8_REGIDX_SPSR:
+ change_spsr(data);
+ break;
+
+ case AVR8_REGIDX_SPCR:
+ change_spcr(data);
+ break;
+
+ case AVR8_REGIDX_SPDR:
+ {
+ m_r[AVR8_REGIDX_SPDR] = data;
+ m_spi_active = true;
+ m_spi_prescale_countdown = 7;
+ m_spi_prescale_count = 0;
+ break;
+ }
+
+ case AVR8_REGIDX_WDTCSR:
+ verboselog(m_pc, 0, "AVR8: WDTCSR = %02x\n", data );
+ //TODO: changed_wdtcsr(data);
+ break;
+
+ case AVR8_REGIDX_CLKPR:
+ verboselog(m_pc, 0, "AVR8: CLKPR = %02x\n", data );
+ //TODO: changed_clkpr(data);
+ break;
+
+ case AVR8_REGIDX_PRR0:
+ verboselog(m_pc, 0, "AVR8: PRR0 = %02x\n", data );
+ //TODO: changed_prr0(data);
+ break;
+
+ case AVR8_REGIDX_PRR1:
+ verboselog(m_pc, 0, "AVR8: PRR1 = %02x\n", data );
+ //TODO: changed_prr1(data);
+ break;
+
+ case AVR8_REGIDX_OSCCAL:
+ verboselog(m_pc, 0, "AVR8: OSCCAL = %02x\n", data );
+ //TODO: changed_osccal(data);
+ break;
+
+ case AVR8_REGIDX_PCICR:
+ verboselog(m_pc, 0, "AVR8: PCICR = %02x\n", data );
+ //TODO: changed_pcicr(data);
+ break;
+
+ case AVR8_REGIDX_EICRA:
+ verboselog(m_pc, 0, "AVR8: EICRA = %02x\n", data );
+ //TODO: changed_eicra(data);
+ break;
+
+ case AVR8_REGIDX_EICRB:
+ verboselog(m_pc, 0, "AVR8: EICRB = %02x\n", data );
+ //TODO: changed_eicrb(data);
+ break;
+
+ case AVR8_REGIDX_PCMSK0:
+ verboselog(m_pc, 0, "AVR8: PCMSK0 = %02x\n", data );
+ //TODO: changed_pcmsk0(data);
+ break;
+
+ case AVR8_REGIDX_PCMSK1:
+ verboselog(m_pc, 0, "AVR8: PCMSK1 = %02x\n", data );
+ //TODO: changed_pcmsk1(data);
+ break;
+
+ case AVR8_REGIDX_PCMSK2:
+ verboselog(m_pc, 0, "AVR8: PCMSK2 = %02x\n", data );
+ //TODO: changed_pcmsk2(data);
+ break;
+
+ case AVR8_REGIDX_TIMSK0:
+ verboselog(m_pc, 0, "AVR8: TIMSK0 = %02x\n", data );
+ m_r[AVR8_REGIDX_TIMSK0] = data;
+ update_interrupt(AVR8_INTIDX_OCF0A);
+ update_interrupt(AVR8_INTIDX_OCF0B);
+ update_interrupt(AVR8_INTIDX_TOV0);
break;
case AVR8_REGIDX_TIMSK1:
@@ -1694,145 +2367,359 @@ WRITE8_MEMBER( avr8_device::regs_w )
update_interrupt(AVR8_INTIDX_TOV1);
break;
- case AVR8_REGIDX_TIFR1:
- verboselog(m_pc, 0, "AVR8: TIFR1 = %02x\n", data );
- m_r[AVR8_REGIDX_TIFR1] &= ~(data & AVR8_TIFR1_MASK);
- update_interrupt(AVR8_INTIDX_ICF1);
- update_interrupt(AVR8_INTIDX_OCF1A);
- update_interrupt(AVR8_INTIDX_OCF1B);
- update_interrupt(AVR8_INTIDX_TOV1);
+ case AVR8_REGIDX_TIMSK2:
+ verboselog(m_pc, 0, "AVR8: TIMSK2 = %02x\n", data );
+ m_r[AVR8_REGIDX_TIMSK2] = data;
+ update_interrupt(AVR8_INTIDX_OCF2A);
+ update_interrupt(AVR8_INTIDX_OCF2B);
+ update_interrupt(AVR8_INTIDX_TOV2);
break;
- case AVR8_REGIDX_TCNT1H:
- AVR8_TCNT1H = data;
+ case AVR8_REGIDX_TIMSK3:
+ verboselog(m_pc, 0, "AVR8: TIMSK3 = %02x\n", data );
+ m_r[AVR8_REGIDX_TIMSK3] = data;
+ update_interrupt(AVR8_INTIDX_OCF3A);
+ update_interrupt(AVR8_INTIDX_OCF3B);
+ update_interrupt(AVR8_INTIDX_TOV3);
+ break;
+
+ case AVR8_REGIDX_TIMSK4:
+ verboselog(m_pc, 0, "AVR8: TIMSK4 = %02x\n", data );
+ m_r[AVR8_REGIDX_TIMSK4] = data;
+ update_interrupt(AVR8_INTIDX_OCF4A);
+ update_interrupt(AVR8_INTIDX_OCF4B);
+ update_interrupt(AVR8_INTIDX_TOV4);
+ break;
+
+ case AVR8_REGIDX_TIMSK5:
+ verboselog(m_pc, 0, "AVR8: TIMSK5 = %02x\n", data );
+ m_r[AVR8_REGIDX_TIMSK5] = data;
+ update_interrupt(AVR8_INTIDX_OCF5A);
+ update_interrupt(AVR8_INTIDX_OCF5B);
+ update_interrupt(AVR8_INTIDX_TOV5);
+ break;
+
+ case AVR8_REGIDX_XMCRA:
+ verboselog(m_pc, 0, "AVR8: XMCRA = %02x\n", data );
+ //TODO: changed_xmcra(data);
+ break;
+
+ case AVR8_REGIDX_XMCRB:
+ verboselog(m_pc, 0, "AVR8: XMCRB = %02x\n", data );
+ //TODO: changed_xmcrb(data);
+ break;
+
+ case AVR8_REGIDX_ADCL:
+ verboselog(m_pc, 0, "AVR8: ADCL = %02x\n", data );
+ //TODO: changed_adcl(data);
+ break;
+
+ case AVR8_REGIDX_ADCH:
+ verboselog(m_pc, 0, "AVR8: ADCH = %02x\n", data );
+ //TODO: changed_adch(data);
+ break;
+
+ case AVR8_REGIDX_ADCSRA:
+ verboselog(m_pc, 0, "AVR8: ADCSRA = %02x\n", data );
+ //TODO: changed_adcsra(data);
+ break;
+
+ case AVR8_REGIDX_ADCSRB:
+ verboselog(m_pc, 0, "AVR8: ADCSRB = %02x\n", data );
+ //TODO: changed_adcsrb(data);
+ break;
+
+ case AVR8_REGIDX_ADMUX:
+ verboselog(m_pc, 0, "AVR8: ADMUX = %02x\n", data );
+ //TODO: changed_admux(data);
+ break;
+
+ case AVR8_REGIDX_DIDR0:
+ verboselog(m_pc, 0, "AVR8: DIDR0 = %02x\n", data );
+ //TODO: changed_didr0(data);
+ break;
+
+ case AVR8_REGIDX_DIDR1:
+ verboselog(m_pc, 0, "AVR8: DIDR1 = %02x\n", data );
+ //TODO: changed_didr1(data);
+ break;
+
+ case AVR8_REGIDX_DIDR2:
+ verboselog(m_pc, 0, "AVR8: DIDR2 = %02x\n", data );
+ //TODO: changed_didr2(data);
+ break;
+
+ case AVR8_REGIDX_TCCR1A:
+ verboselog(m_pc, 0, "AVR8: TCCR1A = %02x\n", data );
+ changed_tccr1a(data);
+ break;
+
+ case AVR8_REGIDX_TCCR1B:
+ verboselog(m_pc, 0, "AVR8: TCCR1B = %02x\n", data );
+ changed_tccr1b(data);
+ break;
+
+ case AVR8_REGIDX_TCCR1C:
+ verboselog(m_pc, 0, "AVR8: TCCR1C = %02x\n", data );
+ //TODO: changed_tccr1c(data);
break;
case AVR8_REGIDX_TCNT1L:
AVR8_TCNT1L = data;
break;
- case AVR8_REGIDX_TCCR2B:
- verboselog(m_pc, 0, "AVR8: TCCR2B = %02x\n", data );
+ case AVR8_REGIDX_TCNT1H:
+ AVR8_TCNT1H = data;
break;
- case AVR8_REGIDX_TCCR2A:
- verboselog(m_pc, 0, "AVR8: TCCR2A = %02x\n", data );
- changed_tccr2a(data);
+ case AVR8_REGIDX_ICR1L:
+ //TODO: ICR1L
break;
- case AVR8_REGIDX_OCR2A:
- update_ocr2(data, AVR8_REG_A);
+ case AVR8_REGIDX_ICR1H:
+ //TODO: ICR1H
break;
- case AVR8_REGIDX_OCR2B:
- update_ocr2(data, AVR8_REG_B);
+ case AVR8_REGIDX_OCR1AL:
+ verboselog(m_pc, 0, "AVR8: OCR1AL = %02x\n", data );
+ update_ocr1((AVR8_OCR1A & 0xff00) | data, AVR8_REG_A);
break;
- case AVR8_REGIDX_TIMSK2:
- verboselog(m_pc, 0, "AVR8: TIMSK2 = %02x\n", data );
- m_r[AVR8_REGIDX_TIMSK2] = data;
- update_interrupt(AVR8_INTIDX_OCF2A);
- update_interrupt(AVR8_INTIDX_OCF2B);
- update_interrupt(AVR8_INTIDX_TOV2);
+ case AVR8_REGIDX_OCR1AH:
+ verboselog(m_pc, 0, "AVR8: OCR1AH = %02x\n", data );
+ update_ocr1((AVR8_OCR1A & 0x00ff) | (data << 8), AVR8_REG_A);
break;
- case AVR8_REGIDX_TIFR2:
- verboselog(m_pc, 0, "AVR8: TIFR2 = %02x\n", data );
- m_r[AVR8_REGIDX_TIFR2] &= ~(data & AVR8_TIFR2_MASK);
- update_interrupt(AVR8_INTIDX_OCF2A);
- update_interrupt(AVR8_INTIDX_OCF2B);
- update_interrupt(AVR8_INTIDX_TOV2);
+ case AVR8_REGIDX_OCR1BL:
+ verboselog(m_pc, 0, "AVR8: OCR1BL = %02x\n", data );
+ update_ocr1((AVR8_OCR1B & 0xff00) | data, AVR8_REG_B);
+ break;
+
+ case AVR8_REGIDX_OCR1BH:
+ verboselog(m_pc, 0, "AVR8: OCR1BH = %02x\n", data );
+ update_ocr1((AVR8_OCR1B & 0x00ff) | (data << 8), AVR8_REG_B);
+ break;
+
+ case AVR8_REGIDX_OCR1CL:
+ verboselog(m_pc, 0, "AVR8: OCR1CL = %02x\n", data );
+ update_ocr1((AVR8_OCR1C & 0xff00) | data, AVR8_REG_C);
+ break;
+
+ case AVR8_REGIDX_OCR1CH:
+ verboselog(m_pc, 0, "AVR8: OCR1CH = %02x\n", data );
+ update_ocr1((AVR8_OCR1C & 0x00ff) | (data << 8), AVR8_REG_C);
+ break;
+
+ case AVR8_REGIDX_TCCR3A:
+ verboselog(m_pc, 0, "AVR8: TCCR3A = %02x\n", data );
+//TODO: changed_tccr3a(data);
+ break;
+
+ case AVR8_REGIDX_TCCR3B:
+ verboselog(m_pc, 0, "AVR8: TCCR3B = %02x\n", data );
+//TODO: changed_tccr3b(data);
+ break;
+
+ case AVR8_REGIDX_TCCR3C:
+ verboselog(m_pc, 0, "AVR8: TCCR3C = %02x\n", data );
+//TODO: changed_tccr3c(data);
+ break;
+
+ case AVR8_REGIDX_TCNT3L:
+ AVR8_TCNT3L = data;
+ break;
+
+ case AVR8_REGIDX_TCNT3H:
+ AVR8_TCNT3H = data;
+ break;
+
+ case AVR8_REGIDX_ICR3L:
+ //TODO: ICR3L
+ break;
+
+ case AVR8_REGIDX_ICR3H:
+ //TODO: ICR3H
+ break;
+
+ case AVR8_REGIDX_OCR3AL:
+ verboselog(m_pc, 0, "AVR8: OCR3AL = %02x\n", data );
+//TODO: update_ocr3((AVR8_OCR3A & 0xff00) | data, AVR8_REG_A);
+ break;
+
+ case AVR8_REGIDX_OCR3AH:
+ verboselog(m_pc, 0, "AVR8: OCR3AH = %02x\n", data );
+//TODO: update_ocr3((AVR8_OCR3A & 0x00ff) | (data << 8), AVR8_REG_A);
+ break;
+
+ case AVR8_REGIDX_OCR3BL:
+ verboselog(m_pc, 0, "AVR8: OCR3BL = %02x\n", data );
+//TODO: update_ocr3((AVR8_OCR3B & 0xff00) | data, AVR8_REG_B);
+ break;
+
+ case AVR8_REGIDX_OCR3BH:
+ verboselog(m_pc, 0, "AVR8: OCR3BH = %02x\n", data );
+//TODO: update_ocr3((AVR8_OCR3B & 0x00ff) | (data << 8), AVR8_REG_B);
+ break;
+
+ case AVR8_REGIDX_OCR3CL:
+ verboselog(m_pc, 0, "AVR8: OCR3CL = %02x\n", data );
+//TODO: update_ocr3((AVR8_OCR3C & 0xff00) | data, AVR8_REG_C);
+ break;
+
+ case AVR8_REGIDX_OCR3CH:
+ verboselog(m_pc, 0, "AVR8: OCR3CH = %02x\n", data );
+//TODO: update_ocr3((AVR8_OCR3C & 0x00ff) | (data << 8), AVR8_REG_C);
+ break;
+
+ case AVR8_REGIDX_TCCR4A:
+ verboselog(m_pc, 0, "AVR8: TCCR4A = %02x\n", data );
+ changed_tccr4a(data);
+ break;
+
+ case AVR8_REGIDX_TCCR4B:
+ verboselog(m_pc, 0, "AVR8: TCCR4B = %02x\n", data );
+ changed_tccr4b(data);
+ break;
+
+ case AVR8_REGIDX_TCCR4C:
+ verboselog(m_pc, 0, "AVR8: TCCR4C = %02x\n", data );
+//TODO: changed_tccr4c(data);
+ break;
+
+ case AVR8_REGIDX_TCNT4L:
+ AVR8_TCNT4L = data;
+ break;
+
+ case AVR8_REGIDX_TCNT4H:
+ AVR8_TCNT4H = data;
+ break;
+
+ case AVR8_REGIDX_ICR4L:
+ //TODO: ICR4L
+ break;
+
+ case AVR8_REGIDX_ICR4H:
+ //TODO: ICR4H
+ break;
+
+ case AVR8_REGIDX_OCR4AL:
+ verboselog(m_pc, 0, "AVR8: OCR4AL = %02x\n", data );
+//TODO: update_ocr4((AVR8_OCR4A & 0xff00) | data, AVR8_REG_A);
+ break;
+
+ case AVR8_REGIDX_OCR4AH:
+ verboselog(m_pc, 0, "AVR8: OCR4AH = %02x\n", data );
+//TODO: update_ocr4((AVR8_OCR4A & 0x00ff) | (data << 8), AVR8_REG_A);
+ break;
+
+ case AVR8_REGIDX_OCR4BL:
+ verboselog(m_pc, 0, "AVR8: OCR4BL = %02x\n", data );
+//TODO: update_ocr4((AVR8_OCR4B & 0xff00) | data, AVR8_REG_B);
+ break;
+
+ case AVR8_REGIDX_OCR4BH:
+ verboselog(m_pc, 0, "AVR8: OCR4BH = %02x\n", data );
+//TODO: update_ocr4((AVR8_OCR4B & 0x00ff) | (data << 8), AVR8_REG_B);
+ break;
+
+ case AVR8_REGIDX_OCR4CL:
+ verboselog(m_pc, 0, "AVR8: OCR4CL = %02x\n", data );
+//TODO: update_ocr4((AVR8_OCR4C & 0xff00) | data, AVR8_REG_C);
+ break;
+
+ case AVR8_REGIDX_OCR4CH:
+ verboselog(m_pc, 0, "AVR8: OCR4CH = %02x\n", data );
+//TODO: update_ocr4((AVR8_OCR4C & 0x00ff) | (data << 8), AVR8_REG_C);
+ break;
+
+ case AVR8_REGIDX_TCCR2A:
+ verboselog(m_pc, 0, "AVR8: TCCR2A = %02x\n", data );
+ changed_tccr2a(data);
+ break;
+
+ case AVR8_REGIDX_TCCR2B:
+ verboselog(m_pc, 0, "AVR8: TCCR2B = %02x\n", data );
+ changed_tccr2b(data);
break;
case AVR8_REGIDX_TCNT2:
AVR8_TCNT2 = data;
break;
- case AVR8_REGIDX_GTCCR:
- if (data & AVR8_GTCCR_PSRASY_MASK)
- {
- data &= ~AVR8_GTCCR_PSRASY_MASK;
- m_timer2_prescale_count = 0;
- }
+ case AVR8_REGIDX_OCR2A:
+ update_ocr2(data, AVR8_REG_A);
break;
- case AVR8_REGIDX_SPL:
- case AVR8_REGIDX_SPH:
- case AVR8_REGIDX_DDRA:
- case AVR8_REGIDX_DDRB:
- case AVR8_REGIDX_DDRC:
- case AVR8_REGIDX_DDRD:
- case AVR8_REGIDX_EEARL:
- case AVR8_REGIDX_EEARH:
- case AVR8_REGIDX_SREG:
- m_r[offset] = data;
+ case AVR8_REGIDX_OCR2B:
+ update_ocr2(data, AVR8_REG_B);
break;
- case AVR8_REGIDX_EECR:
- if (data & AVR8_EECR_EERE)
- {
- UINT16 addr = (m_r[AVR8_REGIDX_EEARH] & AVR8_EEARH_MASK) << 8;
- addr |= m_r[AVR8_REGIDX_EEARL];
- m_r[AVR8_REGIDX_EEDR] = m_eeprom[addr];
- }
+ case AVR8_REGIDX_ASSR:
+ verboselog(m_pc, 0, "AVR8: ASSR = %02x\n", data );
+ //TODO: changed_assr(data);
break;
- case AVR8_REGIDX_GPIOR0:
- verboselog(m_pc, 1, "AVR8: GPIOR0 Write: %02x\n", data);
- m_r[offset] = data;
+ case AVR8_REGIDX_TWBR:
+ verboselog(m_pc, 0, "AVR8: TWBR = %02x\n", data );
+ //TODO: changed_twbr(data);
break;
- case AVR8_REGIDX_GPIOR1:
- case AVR8_REGIDX_GPIOR2:
- m_r[offset] = data;
+ case AVR8_REGIDX_TWSR:
+ verboselog(m_pc, 0, "AVR8: TWSR = %02x\n", data );
+ //TODO: changed_twsr(data);
break;
- case AVR8_REGIDX_PORTA:
- m_io->write_byte(0x00, data);
- m_r[AVR8_REGIDX_PORTA] = data;
+ case AVR8_REGIDX_TWAR:
+ verboselog(m_pc, 0, "AVR8: TWAR = %02x\n", data );
+ //TODO: changed_twar(data);
break;
- case AVR8_REGIDX_PORTB:
- m_io->write_byte(0x01, data);
- m_r[AVR8_REGIDX_PORTB] = data;
+ case AVR8_REGIDX_TWDR:
+ verboselog(m_pc, 0, "AVR8: TWDR = %02x\n", data );
+ //TODO: changed_twdr(data);
break;
- case AVR8_REGIDX_PORTC:
- m_io->write_byte(0x02, data);
- m_r[AVR8_REGIDX_PORTC] = data;
+ case AVR8_REGIDX_TWCR:
+ verboselog(m_pc, 0, "AVR8: TWCR = %02x\n", data );
+ //TODO: changed_twcr(data);
+ m_r[AVR8_REGIDX_TWCR] = data;
break;
- case AVR8_REGIDX_PORTD:
- m_io->write_byte(0x03, data);
- m_r[AVR8_REGIDX_PORTD] = data;
+ case AVR8_REGIDX_TWAMR:
+ verboselog(m_pc, 0, "AVR8: TWAMR = %02x\n", data );
+ //TODO: changed_twamr(data);
break;
- case AVR8_REGIDX_SPSR:
- change_spsr(data);
+ case AVR8_REGIDX_UCSR0A:
+ verboselog(m_pc, 0, "AVR8: UCSR0A = %02x\n", data );
+ //TODO: changed_ucsr0a(data);
break;
- case AVR8_REGIDX_SPCR:
- change_spcr(data);
+ case AVR8_REGIDX_UCSR0B:
+ verboselog(m_pc, 0, "AVR8: UCSR0B = %02x\n", data );
+ //TODO: changed_ucsr0b(data);
break;
- case AVR8_REGIDX_SPDR:
- {
- m_r[AVR8_REGIDX_SPDR] = data;
- m_spi_active = true;
- m_spi_prescale_countdown = 7;
- m_spi_prescale_count = 0;
+ case AVR8_REGIDX_UCSR0C:
+ verboselog(m_pc, 0, "AVR8: UCSR0C = %02x\n", data );
+ //TODO: changed_ucsr0c(data);
break;
- }
-
+/*
+ case AVR8_REGIDX_:
+ verboselog(m_pc, 0, "AVR8: = %02x\n", data );
+ //TODO: changed_(data);
+ break;
+*/
default:
- verboselog(m_pc, 0, "AVR8: Unknown Register Write: %02x = %02x\n", (UINT8)offset, data);
+ verboselog(m_pc, 0, "AVR8: Unknown Register Write: %03x = %02x\n", offset, data);
break;
}
}
READ8_MEMBER( avr8_device::regs_r )
{
- //printf("offset %04x\n", offset);
+// printf("--- READ offset %04x ---\n", offset);
+
switch( offset )
{
case AVR8_REGIDX_R0:
@@ -1869,38 +2756,91 @@ READ8_MEMBER( avr8_device::regs_r )
case AVR8_REGIDX_R31:
return m_r[offset];
- case AVR8_REGIDX_SPL:
- case AVR8_REGIDX_SPH:
- case AVR8_REGIDX_TCNT1L:
- case AVR8_REGIDX_TCNT1H:
- case AVR8_REGIDX_TCNT2:
case AVR8_REGIDX_PORTA:
case AVR8_REGIDX_PORTB:
case AVR8_REGIDX_PORTC:
case AVR8_REGIDX_PORTD:
+ case AVR8_REGIDX_PORTE:
+ case AVR8_REGIDX_PORTF:
+ case AVR8_REGIDX_PORTG:
+ case AVR8_REGIDX_PORTH:
+ case AVR8_REGIDX_PORTJ:
+ case AVR8_REGIDX_PORTK:
+ case AVR8_REGIDX_PORTL:
case AVR8_REGIDX_DDRA:
case AVR8_REGIDX_DDRB:
case AVR8_REGIDX_DDRC:
case AVR8_REGIDX_DDRD:
+ case AVR8_REGIDX_DDRE:
+ case AVR8_REGIDX_DDRF:
+ case AVR8_REGIDX_DDRG:
+ case AVR8_REGIDX_DDRH:
+ case AVR8_REGIDX_DDRJ:
+ case AVR8_REGIDX_DDRK:
+ case AVR8_REGIDX_DDRL:
+ case AVR8_REGIDX_TWCR:/*TODO: needed for Replicator 1 <------- BLOQUEIA PROGRESSO DA EXECUÇÃO DO FIRMWARE no endereço 105EC*/
+ case AVR8_REGIDX_UCSR0B:/*TODO: needed for Replicator 1 */
+ case AVR8_REGIDX_SPDR: /*TODO: needed for Replicator 1 */
+ case AVR8_REGIDX_SPSR: /*TODO: needed for Replicator 1 */
+ case AVR8_REGIDX_ADCSRA: /*TODO: needed for Replicator 1 */
+ case AVR8_REGIDX_ADCSRB: /*TODO: needed for Replicator 1 */
case AVR8_REGIDX_GPIOR0:
case AVR8_REGIDX_GPIOR1:
case AVR8_REGIDX_GPIOR2:
case AVR8_REGIDX_EEDR:
+ case AVR8_REGIDX_SPL:
+ case AVR8_REGIDX_SPH:
case AVR8_REGIDX_SREG:
+ case AVR8_REGIDX_EECR: /*TODO: needed for Replicator 1 */
return m_r[offset];
+ case AVR8_REGIDX_TWSR:
+ //quick hack: by returning a value != 0x08 we induce an error state that makes the object code jump out of the wait loop and continue execution failing the 2-wire write operation.
+ //TODO: implement-me!
+ return 0x00; /*TODO: needed for Replicator 1 */
+
// TODO: consider the DDRx
case AVR8_REGIDX_PINA:
- return m_io->read_byte(AVR8_REG_A);
+ return m_io->read_byte(AVR8_REG_A);
+
case AVR8_REGIDX_PINB:
- return m_io->read_byte(AVR8_REG_B);
+ return m_io->read_byte(AVR8_REG_B);
+
case AVR8_REGIDX_PINC:
- return m_io->read_byte(AVR8_REG_C);
+ return m_io->read_byte(AVR8_REG_C);
+
case AVR8_REGIDX_PIND:
- return m_io->read_byte(AVR8_REG_D);
+ return m_io->read_byte(AVR8_REG_D);
+
+ case AVR8_REGIDX_PINE:
+ return m_io->read_byte(AVR8_REG_E);
+
+ case AVR8_REGIDX_PINF:
+ return m_io->read_byte(AVR8_REG_F);
+
+ case AVR8_REGIDX_PING:
+ return m_io->read_byte(AVR8_REG_G);
+
+ case AVR8_REGIDX_PINH:
+ return m_io->read_byte(AVR8_REG_H);
+
+ case AVR8_REGIDX_PINJ:
+ return m_io->read_byte(AVR8_REG_J);
+
+ case AVR8_REGIDX_PINK:
+ return m_io->read_byte(AVR8_REG_K);
+
+ case AVR8_REGIDX_PINL:
+ return m_io->read_byte(AVR8_REG_L);
+
+ case AVR8_REGIDX_TCNT1L:
+ case AVR8_REGIDX_TCNT1H:
+ case AVR8_REGIDX_TCNT2:
+ case AVR8_REGIDX_UCSR0A:
+ return m_r[offset];
default:
- verboselog(m_pc, 0, "AVR8: Unknown Register Read: %02x\n", (UINT8)offset);
+ printf("[%08X] AVR8: Unknown Register Read: 0x%03X\n", m_shifted_pc, offset);
return 0;
}
}
@@ -1961,6 +2901,7 @@ void avr8_device::execute_run()
UINT8 rr = 0;
UINT8 res = 0;
UINT16 pd = 0;
+ UINT32 pd32 = 0;
INT16 sd = 0;
INT32 opcycles = 1;
@@ -2289,12 +3230,17 @@ void avr8_device::execute_run()
opcycles = 3;
break;
case 0x0006: // ELPM Rd,Z
- //output += sprintf( output, "ELPM R%d, Z", RD5(op) );
- unimplemented_opcode(op);
+ m_r[RD5(op)] = m_program->read_byte((m_r[AVR8_REGIDX_RAMPZ] << 16) | ZREG);
+ opcycles = 3;
break;
case 0x0007: // ELPM Rd,Z+
- //output += sprintf( output, "ELPM R%d, Z+", RD5(op) );
- unimplemented_opcode(op);
+ pd32 = (m_r[AVR8_REGIDX_RAMPZ] << 16) | ZREG;
+ m_r[RD5(op)] = m_program->read_byte(pd32);
+ pd32++;
+ m_r[AVR8_REGIDX_RAMPZ] = (pd32 >> 16) & 0x00ff;
+ m_r[31] = (pd32 >> 8) & 0x00ff;
+ m_r[30] = pd32 & 0x00ff;
+ opcycles = 3;
break;
case 0x0009: // LD Rd,Y+
pd = YREG;
@@ -2303,7 +3249,7 @@ void avr8_device::execute_run()
m_r[29] = (pd >> 8) & 0x00ff;
m_r[28] = pd & 0x00ff;
opcycles = 2;
- break;
+ break;
case 0x000a: // LD Rd,-Y
pd = YREG;
pd--;
@@ -2658,7 +3604,9 @@ void avr8_device::execute_run()
break;
case 0x00a0: // WDR
//output += sprintf( output, "WDR" );
- unimplemented_opcode(op);
+ //unimplemented_opcode(op); //TODO: necessary for emulating the Replicator 1
+ //printf("Watchdot Reset!\n");
+ opcycles = 1;
break;
case 0x00c0: // LPM
m_r[0] = m_program->read_byte(ZREG);
diff --git a/src/emu/cpu/avr8/avr8.h b/src/emu/cpu/avr8/avr8.h
index bd7e5acfad1..48fe5577941 100644
--- a/src/emu/cpu/avr8/avr8.h
+++ b/src/emu/cpu/avr8/avr8.h
@@ -46,6 +46,23 @@
#define MCFG_CPU_AVR8_CONFIG(_config) \
avr8_device::static_set_config(*device, _config);
+
+//**************************************************************************
+// FUSE BITS CONFIGURATION MACROS
+//**************************************************************************
+
+#define MCFG_CPU_AVR8_LFUSE(byte) \
+ ((avr8_device*) device)->set_low_fuses(byte);
+
+#define MCFG_CPU_AVR8_HFUSE(byte) \
+ ((avr8_device*) device)->set_high_fuses(byte);
+
+#define MCFG_CPU_AVR8_EFUSE(byte) \
+ ((avr8_device*) device)->set_extended_fuses(byte);
+
+#define MCFG_CPU_AVR8_LOCK(byte) \
+ ((avr8_device*) device)->set_lock_bits(byte);
+
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
@@ -73,6 +90,12 @@ public:
// inline configuration helpers
static void static_set_config(device_t &device, const avr8_config &config);
+ // fuse configs
+ void set_low_fuses(UINT8 byte);
+ void set_high_fuses(UINT8 byte);
+ void set_extended_fuses(UINT8 byte);
+ void set_lock_bits(UINT8 byte);
+
// public interfaces
virtual void update_interrupt(int source);
UINT64 get_elapsed_cycles()
@@ -83,9 +106,18 @@ public:
// register handling
DECLARE_WRITE8_MEMBER( regs_w );
DECLARE_READ8_MEMBER( regs_r );
+ UINT32 m_shifted_pc;
protected:
- avr8_device(const machine_config &mconfig, const char *name, const char *tag, device_t *owner, UINT32 clock, const device_type type, UINT32 address_mask, address_map_constructor internal_map, const char *shortname, const char *source);
+ enum
+ {
+ CPU_TYPE_ATMEGA88,
+ CPU_TYPE_ATMEGA644,
+ CPU_TYPE_ATMEGA1280,
+ CPU_TYPE_ATMEGA2560
+ };
+
+ avr8_device(const machine_config &mconfig, const char *name, const char *tag, device_t *owner, UINT32 clock, const device_type type, UINT32 address_mask, address_map_constructor internal_map, UINT8 cpu_type, const char *shortname, const char *source);
// device-level overrides
virtual void device_start();
@@ -115,10 +147,19 @@ protected:
const address_space_config m_io_config;
UINT8 *m_eeprom;
+ // bootloader
+ UINT16 m_boot_size;
+ UINT8 m_cpu_type;
+
+ // Fuses
+ UINT8 m_lfuses;
+ UINT8 m_hfuses;
+ UINT8 m_efuses;
+ UINT8 m_lock_bits;
+
// CPU registers
UINT32 m_pc;
- UINT32 m_shifted_pc;
- UINT8 m_r[256];
+ UINT8 m_r[0x200];
// internal timers
UINT8 m_timer0_top;
@@ -136,6 +177,11 @@ protected:
UINT16 m_timer2_prescale;
UINT16 m_timer2_prescale_count;
+ UINT16 m_timer4_top;
+ INT32 m_timer4_increment;
+ UINT16 m_timer4_prescale;
+ UINT16 m_timer4_prescale_count;
+
// SPI
bool m_spi_active;
UINT8 m_spi_prescale;
@@ -209,6 +255,26 @@ protected:
void update_ocr2(UINT8 newval, UINT8 reg);
void timer2_force_output_compare(int reg);
+ // timer 3
+/*
+ void timer3_tick();
+ void changed_tccr3a(UINT8 data);
+ void changed_tccr3b(UINT8 data);
+ void update_timer3_waveform_gen_mode();
+ void update_timer3_clock_source();
+ void update_ocr3(UINT8 newval, UINT8 reg);
+ void timer3_force_output_compare(int reg);
+*/
+
+ // timer 4
+ void timer4_tick();
+ void changed_tccr4a(UINT8 data);
+ void changed_tccr4b(UINT8 data);
+ void update_timer4_waveform_gen_mode();
+ void update_timer4_clock_source();
+ //void update_ocr4(UINT8 newval, UINT8 reg);
+ //void timer4_force_output_compare(int reg);
+
// address spaces
address_space *m_program;
address_space *m_data;
@@ -218,6 +284,8 @@ protected:
// device type definition
extern const device_type ATMEGA88;
extern const device_type ATMEGA644;
+extern const device_type ATMEGA1280;
+extern const device_type ATMEGA2560;
// ======================> atmega88_device
@@ -239,6 +307,28 @@ public:
virtual void update_interrupt(int source);
};
+// ======================> atmega1280_device
+
+class atmega1280_device : public avr8_device
+{
+public:
+ // construction/destruction
+ atmega1280_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ virtual void update_interrupt(int source);
+};
+
+// ======================> atmega2560_device
+
+class atmega2560_device : public avr8_device
+{
+public:
+ // construction/destruction
+ atmega2560_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ virtual void update_interrupt(int source);
+};
+
/***************************************************************************
REGISTER ENUMERATION
***************************************************************************/
@@ -282,7 +372,8 @@ enum
AVR8_X,
AVR8_Y,
AVR8_Z,
- AVR8_SP,
+ AVR8_SPH,
+ AVR8_SPL,
};
enum
@@ -348,7 +439,7 @@ enum
// Used by I/O register handling
enum
{
- AVR8_REGIDX_R0 = 0,
+ AVR8_REGIDX_R0 = 0x00,
AVR8_REGIDX_R1,
AVR8_REGIDX_R2,
AVR8_REGIDX_R3,
@@ -380,7 +471,6 @@ enum
AVR8_REGIDX_R29,
AVR8_REGIDX_R30,
AVR8_REGIDX_R31,
-
AVR8_REGIDX_PINA = 0x20,
AVR8_REGIDX_DDRA,
AVR8_REGIDX_PORTA,
@@ -393,12 +483,22 @@ enum
AVR8_REGIDX_PIND,
AVR8_REGIDX_DDRD,
AVR8_REGIDX_PORTD,
-
+ AVR8_REGIDX_PINE,
+ AVR8_REGIDX_DDRE,
+ AVR8_REGIDX_PORTE,
+ AVR8_REGIDX_PINF,
+ AVR8_REGIDX_DDRF,
+ AVR8_REGIDX_PORTF,
+ AVR8_REGIDX_PING,
+ AVR8_REGIDX_DDRG,
+ AVR8_REGIDX_PORTG,
AVR8_REGIDX_TIFR0 = 0x35,
AVR8_REGIDX_TIFR1,
AVR8_REGIDX_TIFR2,
-
- AVR8_REGIDX_PCIFR = 0x3b,
+ AVR8_REGIDX_TIFR3,
+ AVR8_REGIDX_TIFR4,
+ AVR8_REGIDX_TIFR5,
+ AVR8_REGIDX_PCIFR = 0x3B,
AVR8_REGIDX_EIFR,
AVR8_REGIDX_EIMSK,
AVR8_REGIDX_GPIOR0,
@@ -412,53 +512,66 @@ enum
AVR8_REGIDX_TCNT0,
AVR8_REGIDX_OCR0A,
AVR8_REGIDX_OCR0B,
-
- AVR8_REGIDX_GPIOR1 = 0x4a,
+ //0x49: Reserved
+ AVR8_REGIDX_GPIOR1 = 0x4A,
AVR8_REGIDX_GPIOR2,
AVR8_REGIDX_SPCR,
AVR8_REGIDX_SPSR,
AVR8_REGIDX_SPDR,
-
+ //0x4F: Reserved
AVR8_REGIDX_ACSR = 0x50,
-
+ AVR8_REGIDX_OCDR,
+ //0x52: Reserved
AVR8_REGIDX_SMCR = 0x53,
AVR8_REGIDX_MCUSR,
AVR8_REGIDX_MCUCR,
-
+ //0x56: Reserved
AVR8_REGIDX_SPMCSR = 0x57,
-
- AVR8_REGIDX_SPL = 0x5d,
+ //0x58: Reserved
+ //0x59: Reserved
+ //0x5A: Reserved
+ AVR8_REGIDX_RAMPZ = 0x5B,
+ AVR8_REGIDX_EIND,
+ AVR8_REGIDX_SPL,
AVR8_REGIDX_SPH,
AVR8_REGIDX_SREG,
- AVR8_REGIDX_WDTCSR,
+//--------------------------
+ AVR8_REGIDX_WDTCSR = 0x60,
AVR8_REGIDX_CLKPR,
-
- AVR8_REGIDX_PRR = 0x64,
-
- AVR8_REGIDX_OSCCAL = 0x66,
-
+ //0x62: Reserved
+ //0x63: Reserved
+ AVR8_REGIDX_PRR0 = 0x64,
+ AVR8_REGIDX_PRR1,
+ AVR8_REGIDX_OSCCAL,
+ //0x67: Reserved
AVR8_REGIDX_PCICR = 0x68,
AVR8_REGIDX_EICRA,
-
- AVR8_REGIDX_PCMSK0 = 0x6B,
+ AVR8_REGIDX_EICRB,
+ AVR8_REGIDX_PCMSK0,
AVR8_REGIDX_PCMSK1,
AVR8_REGIDX_PCMSK2,
AVR8_REGIDX_TIMSK0,
AVR8_REGIDX_TIMSK1,
AVR8_REGIDX_TIMSK2,
-
+ AVR8_REGIDX_TIMSK3,
+ AVR8_REGIDX_TIMSK4,
+ AVR8_REGIDX_TIMSK5,
+ AVR8_REGIDX_XMCRA,
+ AVR8_REGIDX_XMCRB,
+ //0x76: Reserved
+ //0x77: Reserved
AVR8_REGIDX_ADCL = 0x78,
AVR8_REGIDX_ADCH,
AVR8_REGIDX_ADCSRA,
AVR8_REGIDX_ADCSRB,
AVR8_REGIDX_ADMUX,
-
- AVR8_REGIDX_DIDR0 = 0x7e,
+ AVR8_REGIDX_DIDR2,
+ AVR8_REGIDX_DIDR0,
AVR8_REGIDX_DIDR1,
AVR8_REGIDX_TCCR1A,
AVR8_REGIDX_TCCR1B,
AVR8_REGIDX_TCCR1C,
-
+ //0x83: Reserved
AVR8_REGIDX_TCNT1L = 0x84,
AVR8_REGIDX_TCNT1H,
AVR8_REGIDX_ICR1L,
@@ -467,56 +580,246 @@ enum
AVR8_REGIDX_OCR1AH,
AVR8_REGIDX_OCR1BL,
AVR8_REGIDX_OCR1BH,
-
- AVR8_REGIDX_TCCR2A = 0xb0,
+ AVR8_REGIDX_OCR1CL,
+ AVR8_REGIDX_OCR1CH,
+ //0x8E: Reserved
+ //0x8F: Reserved
+ AVR8_REGIDX_TCCR3A = 0x90,
+ AVR8_REGIDX_TCCR3B,
+ AVR8_REGIDX_TCCR3C,
+ //0x93: Reserved
+ AVR8_REGIDX_TCNT3L = 0x94,
+ AVR8_REGIDX_TCNT3H,
+ AVR8_REGIDX_ICR3L,
+ AVR8_REGIDX_ICR3H,
+ AVR8_REGIDX_OCR3AL,
+ AVR8_REGIDX_OCR3AH,
+ AVR8_REGIDX_OCR3BL,
+ AVR8_REGIDX_OCR3BH,
+ AVR8_REGIDX_OCR3CL,
+ AVR8_REGIDX_OCR3CH,
+ //0x9E: Reserved
+ //0x9F: Reserved
+ AVR8_REGIDX_TCCR4A = 0xA0,
+ AVR8_REGIDX_TCCR4B,
+ AVR8_REGIDX_TCCR4C,
+ //0xA3: Reserved
+ AVR8_REGIDX_TCNT4L = 0xA4,
+ AVR8_REGIDX_TCNT4H,
+ AVR8_REGIDX_ICR4L,
+ AVR8_REGIDX_ICR4H,
+ AVR8_REGIDX_OCR4AL,
+ AVR8_REGIDX_OCR4AH,
+ AVR8_REGIDX_OCR4BL,
+ AVR8_REGIDX_OCR4BH,
+ AVR8_REGIDX_OCR4CL,
+ AVR8_REGIDX_OCR4CH,
+ //0xAE: Reserved
+ //0xAF: Reserved
+ AVR8_REGIDX_TCCR2A = 0xB0,
AVR8_REGIDX_TCCR2B,
AVR8_REGIDX_TCNT2,
AVR8_REGIDX_OCR2A,
AVR8_REGIDX_OCR2B,
-
- AVR8_REGIDX_ASSR = 0xb6,
-
- AVR8_REGIDX_TWBR = 0xb8,
+ //0xB5: Reserved
+ AVR8_REGIDX_ASSR = 0xB6,
+ //0xB7: Reserved
+ AVR8_REGIDX_TWBR = 0xB8,
AVR8_REGIDX_TWSR,
AVR8_REGIDX_TWAR,
AVR8_REGIDX_TWDR,
AVR8_REGIDX_TWCR,
AVR8_REGIDX_TWAMR,
-
- AVR8_REGIDX_UCSR0A = 0xc0,
+ //0xBE: Reserved
+ //0xBF: Reserved
+ AVR8_REGIDX_UCSR0A = 0xC0,
AVR8_REGIDX_UCSR0B,
AVR8_REGIDX_UCSR0C,
-
- AVR8_REGIDX_UBRR0L = 0xc4,
+ //0xC3: Reserved
+ AVR8_REGIDX_UBRR0L = 0xC4,
AVR8_REGIDX_UBRR0H,
- AVR8_REGIDX_UDR0
+ AVR8_REGIDX_UDR0,
+ //0xC7: Reserved
+ AVR8_REGIDX_UCSR1A = 0xC8,
+ AVR8_REGIDX_UCSR1B,
+ AVR8_REGIDX_UCSR1C,
+ //0xCB: Reserved
+ AVR8_REGIDX_UBRR1L = 0xCC,
+ AVR8_REGIDX_UBRR1H,
+ AVR8_REGIDX_UDR1,
+ //0xCF: Reserved
+ AVR8_REGIDX_UCSR2A = 0xD0,
+ AVR8_REGIDX_UCSR2B,
+ AVR8_REGIDX_UCSR2C,
+ //0xD3: Reserved
+ AVR8_REGIDX_UBRR2L = 0xD4,
+ AVR8_REGIDX_UBRR2H,
+ AVR8_REGIDX_UDR2,
+ //0xD7: Reserved
+ //0xD8: Reserved
+ //0xD9: Reserved
+ //0xDA: Reserved
+ //0xDB: Reserved
+ //0xDC: Reserved
+ //0xDD: Reserved
+ //0xDE: Reserved
+ //0xDF: Reserved
+ //0xE0: Reserved
+ //0xE1: Reserved
+ //0xE2: Reserved
+ //0xE3: Reserved
+ //0xE4: Reserved
+ //0xE5: Reserved
+ //0xE6: Reserved
+ //0xE7: Reserved
+ //0xE8: Reserved
+ //0xE9: Reserved
+ //0xEA: Reserved
+ //0xEB: Reserved
+ //0xEC: Reserved
+ //0xED: Reserved
+ //0xEE: Reserved
+ //0xEF: Reserved
+ //0xF0: Reserved
+ //0xF1: Reserved
+ //0xF2: Reserved
+ //0xF3: Reserved
+ //0xF4: Reserved
+ //0xF5: Reserved
+ //0xF6: Reserved
+ //0xF7: Reserved
+ //0xF8: Reserved
+ //0xF9: Reserved
+ //0xFA: Reserved
+ //0xFB: Reserved
+ //0xFC: Reserved
+ //0xFD: Reserved
+ //0xFE: Reserved
+ //0xFF: Reserved
+ AVR8_REGIDX_PINH = 0x100,
+ AVR8_REGIDX_DDRH,
+ AVR8_REGIDX_PORTH,
+ AVR8_REGIDX_PINJ,
+ AVR8_REGIDX_DDRJ,
+ AVR8_REGIDX_PORTJ,
+ AVR8_REGIDX_PINK,
+ AVR8_REGIDX_DDRK,
+ AVR8_REGIDX_PORTK,
+ AVR8_REGIDX_PINL,
+ AVR8_REGIDX_DDRL,
+ AVR8_REGIDX_PORTL
};
+enum {
+ AVR8_IO_PORTA = 0,
+ AVR8_IO_PORTB,
+ AVR8_IO_PORTC,
+ AVR8_IO_PORTD,
+ AVR8_IO_PORTE,
+ AVR8_IO_PORTF,
+ AVR8_IO_PORTG,
+ AVR8_IO_PORTH,
+ AVR8_IO_PORTJ,
+ AVR8_IO_PORTK,
+ AVR8_IO_PORTL
+};
+
+//TODO: AVR8_REG_* and AVR8_IO_PORT* seem to serve the same purpose and thus should be unified. Verify this!
enum
{
AVR8_REG_A = 0,
AVR8_REG_B,
AVR8_REG_C,
AVR8_REG_D,
+ AVR8_REG_E,
+ AVR8_REG_F,
+ AVR8_REG_G,
+ AVR8_REG_H,
+ AVR8_REG_J,
+ AVR8_REG_K,
+ AVR8_REG_L,
};
enum
{
AVR8_INTIDX_SPI,
+
AVR8_INTIDX_OCF0B,
AVR8_INTIDX_OCF0A,
AVR8_INTIDX_TOV0,
+
AVR8_INTIDX_ICF1,
+
AVR8_INTIDX_OCF1B,
AVR8_INTIDX_OCF1A,
AVR8_INTIDX_TOV1,
+
AVR8_INTIDX_OCF2B,
AVR8_INTIDX_OCF2A,
AVR8_INTIDX_TOV2,
+//------ TODO: review this --------
+ AVR8_INTIDX_OCF3B,
+ AVR8_INTIDX_OCF3A,
+ AVR8_INTIDX_TOV3,
+
+ AVR8_INTIDX_OCF4B,
+ AVR8_INTIDX_OCF4A,
+ AVR8_INTIDX_TOV4,
+
+ AVR8_INTIDX_OCF5B,
+ AVR8_INTIDX_OCF5A,
+ AVR8_INTIDX_TOV5,
+//---------------------------------
+
AVR8_INTIDX_COUNT,
};
+//lock bit masks
+enum
+{
+ LB1 = (1 << 0),
+ LB2 = (1 << 1),
+ BLB01 = (1 << 2),
+ BLB02 = (1 << 3),
+ BLB11 = (1 << 4),
+ BLB12 = (1 << 5),
+};
+
+//extended fuses bit masks
+enum
+{
+ BODLEVEL0 = (1 << 0),
+ BODLEVEL1 = (1 << 1),
+ BODLEVEL2 = (1 << 2),
+};
+
+//high fuses bit masks
+enum
+{
+ BOOTRST = (1 << 0),
+ BOOTSZ0 = (1 << 1),
+ BOOTSZ1 = (1 << 2),
+ EESAVE = (1 << 3),
+ WDTON = (1 << 4),
+ SPIEN = (1 << 5),
+ JTAGEN = (1 << 6),
+ OCDEN = (1 << 7),
+};
+
+//low fuses bit masks
+enum
+{
+ CKSEL0 = (1 << 0),
+ CKSEL1 = (1 << 1),
+ CKSEL2 = (1 << 2),
+ CKSEL3 = (1 << 3),
+ SUT0 = (1 << 4),
+ SUT1 = (1 << 5),
+ CKOUT = (1 << 6),
+ CKDIV8 = (1 << 7),
+};
+
#define AVR8_EECR_EERE 0x01
#define AVR8_EEARH_MASK 0x01
diff --git a/src/emu/cpu/avr8/avr8dasm.c b/src/emu/cpu/avr8/avr8dasm.c
index b356ccf1c71..cadb528f64c 100644
--- a/src/emu/cpu/avr8/avr8dasm.c
+++ b/src/emu/cpu/avr8/avr8dasm.c
@@ -30,6 +30,8 @@ CPU_DISASSEMBLE( avr8 )
UINT32 op = oprom[pos++];
op |= oprom[pos++] << 8;
UINT32 addr = 0;
+ const char* register_names[0x40] = {"PINA", "DDRA", "PORTA", "PINB", "DDRB", "PORTB", "PINC", "DDRC", "PORTC", "PIND", "DDRD", "PORTD", "PINE", "DDRE", "PORTE", "PINF", "DDRF", "PORTF", "PING", "DDRG", "PORTG", "TIFR0", "TIFR1", "TIFR2","TIFR3", "TIFR4", "TIFR5", "PCIFR", "EIFR", "EIMSK", "GPIOR0", "EECR", "EEDR", "EEARL", "EEARH", "GTCCR", "TCCR0A", "TCCR0B", "TCNT0", "OCR0A", "OCR0B", "0x29", "GPIOR1", "GPIOR2", "SPCR", "SPSR", "SPDR", "0x2F", "ACSR", "OCDR", "0x32", "SMCR", "MCUSR", "MCUCR", "0x36", "SPMCSR", "0x38", "0x39", "0x3A", "RAMPZ", "EIND", "SPL", "SPH", "SREG"};
+
switch(op & 0xf000)
{
case 0x0000:
@@ -478,11 +480,19 @@ CPU_DISASSEMBLE( avr8 )
case 0xb000:
if(op & 0x0800)
{
- output += sprintf( output, "OUT 0x%02x, R%d", ACONST6(op), RD5(op) );
+ if (ACONST6(op) < 0x40 ) {
+ output += sprintf( output, "OUT %s, R%d", register_names[ACONST6(op)], RD5(op) );
+ } else {
+ output += sprintf( output, "OUT 0x%02x, R%d", ACONST6(op), RD5(op) );
+ }
}
else
{
- output += sprintf( output, "IN R%d, 0x%02x", RD5(op), ACONST6(op) );
+ if (ACONST6(op) < 0x40 ) {
+ output += sprintf( output, "IN R%d, %s", RD5(op), register_names[ACONST6(op)] );
+ } else {
+ output += sprintf( output, "IN R%d, 0x%02x", RD5(op), ACONST6(op) );
+ }
}
break;
case 0xc000:
diff --git a/src/mess/drivers/craft.c b/src/mess/drivers/craft.c
index f6a89221f62..c6a15b7a04e 100644
--- a/src/mess/drivers/craft.c
+++ b/src/mess/drivers/craft.c
@@ -106,11 +106,11 @@ WRITE8_MEMBER(craft_state::port_w)
{
switch( offset )
{
- case 0x00: // Port A
+ case AVR8_IO_PORTA: // Port A
// Unhandled
break;
- case 0x01: // Port B
+ case AVR8_IO_PORTB: // Port B
{
UINT8 old_port_b = m_port_b;
UINT8 pins = data;
@@ -129,13 +129,13 @@ WRITE8_MEMBER(craft_state::port_w)
break;
}
- case 0x02: // Port C
+ case AVR8_IO_PORTC: // Port C
video_update();
m_port_c = data;
m_latched_color = m_port_c;
break;
- case 0x03: // Port D
+ case AVR8_IO_PORTD: // Port D
{
m_port_d = data;
UINT8 audio_sample = (data & 0x02) | ((data & 0xf4) >> 2);
@@ -189,7 +189,7 @@ static ADDRESS_MAP_START( craft_data_map, AS_DATA, 8, craft_state )
ADDRESS_MAP_END
static ADDRESS_MAP_START( craft_io_map, AS_IO, 8, craft_state )
- AM_RANGE(0x00, 0x03) AM_READWRITE( port_r, port_w )
+ AM_RANGE(AVR8_IO_PORTA, AVR8_IO_PORTD) AM_READWRITE( port_r, port_w )
ADDRESS_MAP_END
/****************************************************\
diff --git a/src/mess/drivers/replicator.c b/src/mess/drivers/replicator.c
new file mode 100644
index 00000000000..70ece6e4a5c
--- /dev/null
+++ b/src/mess/drivers/replicator.c
@@ -0,0 +1,682 @@
+/*
+ Replicator 1 desktop 3d printer
+
+ driver by Felipe CorrĂȘa da Silva Sanches <fsanches@metamaquina.com.br>
+
+ Licensed under GPLv2 or later.
+
+ NOTE: Even though the MAME/MESS project has been adopting a non-commercial additional licensing clause, I do allow commercial usage of my portion of the code according to the plain terms of the GPL license (version 2 or later). This is useful if you happen to use my code in another project or in case the other MAME/MESS developers happen to drop the non-comercial clause completely. I suggest that other developers consider doing the same. --Felipe Sanches
+
+Changelog:
+
+ 2013 DEC 28 [Felipe Sanches]:
+ * LCD now works. We can see the firmware boot screen :-)
+
+ 2013 DEC 24 [Felipe Sanches]:
+ * declaration of internal EEPROM
+
+ 2013 DEC 18 [Felipe Sanches]:
+ * Initial driver skeleton
+
+*/
+
+// TODO:
+// * figure out what's wrong with the keypad inputs (interface seems to be blocked in the first screen)
+// * fix avr8 timer/counter #4 so that we get the buzzer to work
+// * figure-out correct size of internal EEPROM
+// * emulate an SD Card
+// * implement avr8 WDR (watchdog reset) opcode
+
+#define LOG_PORTS 0
+
+//Port A bits:
+//Bit 0 unused
+//Bit 1 unused
+#define A_AXIS_DIR (1 << 2)
+#define A_AXIS_STEP (1 << 3)
+#define A_AXIS_EN (1 << 4)
+#define A_AXIS_POT (1 << 5)
+#define B_AXIS_DIR (1 << 6)
+#define B_AXIS_STEP (1 << 7)
+
+//Port B bits:
+#define SD_CS (1 << 0)
+#define SCK_1280 (1 << 1)
+#define MOSI_1280 (1 << 2)
+#define MISO_1280 (1 << 3)
+#define EX2_PWR_CHECK (1 << 4)
+#define EX2_HEAT (1 << 5)
+#define EX2_FAN (1 << 6)
+#define BLINK (1 << 7)
+
+//Port C bits:
+#define EX2_1280 (1 << 0)
+#define EX1_1280 (1 << 1)
+#define LCD_CLK (1 << 2)
+#define LCD_DATA (1 << 3)
+#define LCD_STROBE (1 << 4)
+#define RLED (1 << 5)
+#define GLED (1 << 6)
+#define DETECT (1 << 7)
+
+//Port D bits:
+#define PORTD_SCL (1 << 0)
+#define PORTD_SDA (1 << 1)
+#define EX_RX_1280 (1 << 2)
+#define EX_TX_1280 (1 << 3)
+//Bit 4 unused
+//Bit 5 unused
+//Bit 6 unused
+//Bit 7 unused
+
+//Port E bits:
+#define RX_1280 (1 << 0)
+#define TX_1280 (1 << 1)
+#define THERMO_SCK (1 << 2)
+#define THERMO_CS1 (1 << 3)
+#define THERMO_CS2 (1 << 4)
+#define THERMO_DO (1 << 5)
+//Bit 6 unused
+//Bit 7 unused
+
+//Port F bits:
+#define X_AXIS_DIR (1 << 0)
+#define X_AXIS_STEP (1 << 1)
+#define X_AXIS_EN (1 << 2)
+#define X_AXIS_POT (1 << 3)
+#define Y_AXIS_DIR (1 << 4)
+#define Y_AXIS_STEP (1 << 5)
+#define Y_AXIS_EN (1 << 6)
+#define Y_AXIS_POT (1 << 7)
+
+//Port G bits:
+#define EX4_1280 (1 << 0)
+#define EX3_1280 (1 << 1)
+#define B_AXIS_EN (1 << 2)
+//Bit 3 unused
+#define CUTOFF_SR_CHECK (1 << 4)
+#define BUZZ (1 << 5)
+//Bit 6 unused
+//Bit 7 unused
+
+//Port H bits:
+#define CUTOFF_TEST (1 << 0)
+#define CUTOFF_RESET (1 << 1)
+#define EX1_PWR_CHECK (1 << 2)
+#define EX1_HEAT (1 << 3)
+#define EX1_FAN (1 << 4)
+#define SD_WP (1 << 5)
+#define SD_CD (1 << 6)
+//Bit 7 unused
+
+//Port J bits:
+#define BUTTON_CENTER (1 << 0)
+#define BUTTON_RIGHT (1 << 1)
+#define BUTTON_LEFT (1 << 2)
+#define BUTTON_DOWN (1 << 3)
+#define BUTTON_UP (1 << 4)
+#define POTS_SCL (1 << 5)
+#define B_AXIS_POT (1 << 6)
+//Bit 7 unused
+
+//Port K bits:
+#define Z_AXIS_DIR (1 << 0)
+#define Z_AXIS_STEP (1 << 1)
+#define Z_AXIS_EN (1 << 2)
+#define Z_AXIS_POT (1 << 3)
+#define EX7_1280 (1 << 4)
+#define EX6_1280 (1 << 5)
+#define EX5_1280 (1 << 6)
+#define HBP_THERM (1 << 7)
+
+//Port L bits:
+#define X_MIN (1 << 0)
+#define X_MAX (1 << 1)
+#define Y_MIN (1 << 2)
+#define Y_MAX (1 << 3)
+#define HBP (1 << 4)
+#define EXTRA_FET (1 << 5)
+#define Z_MIN (1 << 6)
+#define Z_MAX (1 << 7)
+
+
+#include "emu.h"
+#include "cpu/avr8/avr8.h"
+#include "video/hd44780.h"
+#include "rendlay.h"
+#include "debugger.h"
+
+#define MASTER_CLOCK 16000000
+
+/****************************************************\
+* I/O devices *
+\****************************************************/
+
+class replicator_state : public driver_device
+{
+public:
+ replicator_state(const machine_config &mconfig, device_type type, const char *tag)
+ : driver_device(mconfig, type, tag),
+ m_maincpu(*this, "maincpu"),
+ m_lcdc(*this, "hd44780")
+ {
+ }
+
+ virtual void machine_start();
+
+ UINT8 m_port_a;
+ UINT8 m_port_b;
+ UINT8 m_port_c;
+ UINT8 m_port_d;
+ UINT8 m_port_e;
+ UINT8 m_port_f;
+ UINT8 m_port_g;
+ UINT8 m_port_h;
+ UINT8 m_port_j;
+ UINT8 m_port_k;
+ UINT8 m_port_l;
+
+ UINT8 shift_register_value;
+
+ required_device<avr8_device> m_maincpu;
+ required_device<hd44780_device> m_lcdc;
+
+ DECLARE_READ8_MEMBER(port_r);
+ DECLARE_WRITE8_MEMBER(port_w);
+ DECLARE_DRIVER_INIT(replicator);
+ virtual void machine_reset();
+ virtual void palette_init();
+};
+
+void replicator_state::machine_start()
+{
+}
+
+READ8_MEMBER(replicator_state::port_r)
+{
+ switch( offset )
+ {
+ case AVR8_IO_PORTA:
+ {
+#if LOG_PORTS
+ printf("[%08X] Port A READ (A-axis signals + B-axis STEP&DIR)\n", m_maincpu->m_shifted_pc);
+#endif
+ return 0x00;
+ break;
+ }
+ case AVR8_IO_PORTB:
+ {
+#if LOG_PORTS
+ printf("[%08X] Port B READ (SD-CS; 1280-MISO/MOSI/SCK; EX2-FAN/HEAT/PWR-CHECK; BLINK)\n", m_maincpu->m_shifted_pc);
+#endif
+ return 0x00;
+ break;
+ }
+ case AVR8_IO_PORTC:
+ {
+#if LOG_PORTS
+ printf("[%08X] Port C READ (1280-EX1/EX2; LCD-signals; R&G-LED; DETECT)\n", m_maincpu->m_shifted_pc);
+#endif
+ return DETECT; //indicated that the Interface board is present.
+ break;
+ }
+ case AVR8_IO_PORTD:
+ {
+#if LOG_PORTS
+ printf("[%08X] Port D READ (SDA/SCL; 1280-EX-TX/RX)\n", m_maincpu->m_shifted_pc);
+#endif
+ return 0x00;
+ break;
+ }
+ case AVR8_IO_PORTE:
+ {
+#if LOG_PORTS
+ printf("[%08X] Port E READ (1280-TX/RX; THERMO-signals)\n", m_maincpu->m_shifted_pc);
+#endif
+ return 0x00;
+ break;
+ }
+ case AVR8_IO_PORTF:
+ {
+#if LOG_PORTS
+ printf("[%08X] Port F READ (X-axis & Y-axis signals)\n", m_maincpu->m_shifted_pc);
+#endif
+ return 0x00;
+ break;
+ }
+ case AVR8_IO_PORTG:
+ {
+#if LOG_PORTS
+ printf("[%08X] Port G READ (BUZZ; Cutoff-sr-check; B-axis EN; 1280-EX3/EX4)\n", m_maincpu->m_shifted_pc);
+#endif
+ return 0x00;
+ break;
+ }
+ case AVR8_IO_PORTH:
+ {
+#if LOG_PORTS
+ printf("[%08X] Port H READ (cuttoff-text/reset; EX1-FAN/HEAT/PWR-CHECK; SD-CD/SD-WP)\n", m_maincpu->m_shifted_pc);
+#endif
+ return 0x00;
+ break;
+ }
+ case AVR8_IO_PORTJ:
+ {
+#if LOG_PORTS
+ printf("[%08X] Port J READ (Interface buttons; POTS-SCL; B-axis-POT)\n", m_maincpu->m_shifted_pc);
+#endif
+ return ioport("keypad")->read();
+ break;
+ }
+ case AVR8_IO_PORTK:
+ {
+#if LOG_PORTS
+ printf("[%08X] Port K READ (Z-axis signals; HBP-THERM; 1280-EX5/6/7)\n", m_maincpu->m_shifted_pc);
+#endif
+ return 0x00;
+ break;
+ }
+ case AVR8_IO_PORTL:
+ {
+#if LOG_PORTS
+ printf("[%08X] Port L READ (HBP; EXTRA-FET; X-MIN/MAX; Y-MIN/MAX; Z-MIN/MAX)\n", m_maincpu->m_shifted_pc);
+#endif
+ return 0x00;
+ break;
+ }
+ }
+ return 0;
+}
+
+WRITE8_MEMBER(replicator_state::port_w)
+{
+ switch( offset )
+ {
+ case AVR8_IO_PORTA:
+ {
+ if (data == m_port_a) break;
+
+#if LOG_PORTS
+ UINT8 old_port_a = m_port_a;
+ UINT8 changed = data ^ old_port_a;
+
+ printf("[%08X] ", m_maincpu->m_shifted_pc);
+ if(changed & A_AXIS_DIR) printf("[A] A_AXIS_DIR: %s\n", data & A_AXIS_DIR ? "HIGH" : "LOW");
+ if(changed & A_AXIS_STEP) printf("[A] A_AXIS_STEP: %s\n", data & A_AXIS_STEP ? "HIGH" : "LOW");
+ if(changed & A_AXIS_EN) printf("[A] A_AXIS_EN: %s\n", data & A_AXIS_EN ? "HIGH" : "LOW");
+ if(changed & A_AXIS_POT) printf("[A] A_AXIS_POT: %s\n", data & A_AXIS_POT ? "HIGH" : "LOW");
+ if(changed & B_AXIS_DIR) printf("[A] B_AXIS_DIR: %s\n", data & B_AXIS_DIR ? "HIGH" : "LOW");
+ if(changed & B_AXIS_STEP) printf("[A] B_AXIS_STEP: %s\n", data & B_AXIS_STEP ? "HIGH" : "LOW");
+#endif
+
+ m_port_a = data;
+ break;
+ }
+ case AVR8_IO_PORTB:
+ {
+ if (data == m_port_b) break;
+
+#if LOG_PORTS
+ UINT8 old_port_b = m_port_b;
+ UINT8 changed = data ^ old_port_b;
+
+ printf("[%08X] ", m_maincpu->m_shifted_pc);
+ if(changed & SD_CS) printf("[B] SD Card Chip Select: %s\n", data & SD_CS ? "HIGH" : "LOW");
+ if(changed & SCK_1280) printf("[B] 1280-SCK: %s\n", data & SCK_1280 ? "HIGH" : "LOW");
+ if(changed & MOSI_1280) printf("[B] 1280-MOSI: %s\n", data & MOSI_1280 ? "HIGH" : "LOW");
+ if(changed & MISO_1280) printf("[B] 1280-MISO: %s\n", data & MISO_1280 ? "HIGH" : "LOW");
+ if(changed & EX2_PWR_CHECK) printf("[B] EX2-PWR-CHECK: %s\n", data & EX2_PWR_CHECK ? "HIGH" : "LOW");
+ if(changed & EX2_HEAT) printf("[B] EX2_HEAT: %s\n", data & EX2_HEAT ? "HIGH" : "LOW");
+ if(changed & EX2_FAN) printf("[B] EX2_FAN: %s\n", data & EX2_FAN ? "HIGH" : "LOW");
+ if(changed & BLINK) printf("[B] BLINK: %s\n", data & BLINK ? "HIGH" : "LOW");
+#endif
+
+ m_port_b = data;
+ break;
+ }
+ case AVR8_IO_PORTC:
+ {
+ if (data == m_port_c) break;
+
+ UINT8 old_port_c = m_port_c;
+ UINT8 changed = data ^ old_port_c;
+#if LOG_PORTS
+ printf("[%08X] ", m_maincpu->m_shifted_pc);
+ if(changed & EX2_1280) printf("[C] EX2_1280: %s\n", data & EX2_1280 ? "HIGH" : "LOW");
+ if(changed & EX1_1280) printf("[C] EX1_1280: %s\n", data & EX1_1280 ? "HIGH" : "LOW");
+ if(changed & LCD_CLK) printf("[C] LCD_CLK: %s\n", data & LCD_CLK ? "HIGH" : "LOW");
+ if(changed & LCD_DATA) printf("[C] LCD_DATA: %s\n", data & LCD_DATA ? "HIGH" : "LOW");
+ if(changed & LCD_STROBE) printf("[C] LCD_STROBE: %s\n", data & LCD_STROBE ? "HIGH" : "LOW");
+ if(changed & RLED) printf("[C] RLED: %s\n", data & RLED ? "HIGH" : "LOW");
+ if(changed & GLED) printf("[C] GLED: %s\n", data & GLED ? "HIGH" : "LOW");
+ if(changed & DETECT) printf("[C] DETECT: %s\n", data & DETECT ? "HIGH" : "LOW");
+#endif
+
+ if (changed & LCD_CLK){
+ /* The LCD is interfaced by an 8-bit shift register (74HC4094). */
+ if (data & LCD_CLK){//CLK positive edge
+ shift_register_value = (shift_register_value << 1) | ((data & LCD_DATA) >> 3);
+ //printf("[%08X] ", m_maincpu->m_shifted_pc);
+ //printf("[C] LCD CLK positive edge. shift_register=0x%02X\n", shift_register_value);
+ }
+ }
+
+ if(changed & LCD_STROBE){
+ if (data & LCD_STROBE){ //STROBE positive edge
+ bool RS = (shift_register_value >> 1) & 1;
+ bool RW = (shift_register_value >> 2) & 1;
+ bool enable = (shift_register_value >> 3) & 1;
+ UINT8 lcd_data = shift_register_value & 0xF0;
+
+ if (enable && RW==0){
+ if (RS==0){
+ m_lcdc->control_write(space, 0, lcd_data);
+ } else {
+ m_lcdc->data_write(space, 0, lcd_data);
+ }
+ }
+ }
+ }
+ m_port_c = data;
+
+ break;
+ }
+ case AVR8_IO_PORTD:
+ {
+ if (data == m_port_d) break;
+
+#if LOG_PORTS
+ UINT8 old_port_d = m_port_d;
+ UINT8 changed = data ^ old_port_d;
+
+ printf("[%08X] ", m_maincpu->m_shifted_pc);
+ if(changed & PORTD_SCL) printf("[D] PORTD_SCL: %s\n", data & PORTD_SCL ? "HIGH" : "LOW");
+ if(changed & PORTD_SDA) printf("[D] PORTD_SDA: %s\n", data & PORTD_SDA ? "HIGH" : "LOW");
+ if(changed & EX_RX_1280) printf("[D] EX_RX_1280: %s\n", data & EX_RX_1280 ? "HIGH" : "LOW");
+ if(changed & EX_TX_1280) printf("[D] EX_TX_1280: %s\n", data & EX_TX_1280 ? "HIGH" : "LOW");
+#endif
+
+ m_port_d = data;
+ break;
+ }
+ case AVR8_IO_PORTE:
+ {
+ if (data == m_port_e) break;
+
+#if LOG_PORTS
+ UINT8 old_port_e = m_port_e;
+ UINT8 changed = data ^ old_port_e;
+
+ printf("[%08X] ", m_maincpu->m_shifted_pc);
+ if(changed & RX_1280) printf("[E] 1280-RX: %s\n", data & RX_1280 ? "HIGH" : "LOW");
+ if(changed & TX_1280) printf("[E] 1280-TX: %s\n", data & TX_1280 ? "HIGH" : "LOW");
+ if(changed & THERMO_SCK) printf("[E] THERMO-SCK: %s\n", data & THERMO_SCK ? "HIGH" : "LOW");
+ if(changed & THERMO_CS1) printf("[E] THERMO-CS1: %s\n", data & THERMO_CS1 ? "HIGH" : "LOW");
+ if(changed & THERMO_CS2) printf("[E] THERMO-CS2: %s\n", data & THERMO_CS2 ? "HIGH" : "LOW");
+ if(changed & THERMO_DO) printf("[E] THERMO-DO: %s\n", data & THERMO_DO ? "HIGH" : "LOW");
+#endif
+
+ m_port_e = data;
+ break;
+ }
+ case AVR8_IO_PORTF:
+ {
+ if (data == m_port_f) break;
+
+#if LOG_PORTS
+ UINT8 old_port_f = m_port_f;
+ UINT8 changed = data ^ old_port_f;
+
+ printf("[%08X] ", m_maincpu->m_shifted_pc);
+ if(changed & X_AXIS_DIR) printf("[F] X_AXIS_DIR: %s\n", data & X_AXIS_DIR ? "HIGH" : "LOW");
+ if(changed & X_AXIS_STEP) printf("[F] X_AXIS_STEP: %s\n", data & X_AXIS_STEP ? "HIGH" : "LOW");
+ if(changed & X_AXIS_EN) printf("[F] X_AXIS_EN: %s\n", data & X_AXIS_EN ? "HIGH" : "LOW");
+ if(changed & X_AXIS_POT) printf("[F] X_AXIS_POT: %s\n", data & X_AXIS_POT ? "HIGH" : "LOW");
+ if(changed & Y_AXIS_DIR) printf("[F] Y_AXIS_DIR: %s\n", data & Y_AXIS_DIR ? "HIGH" : "LOW");
+ if(changed & Y_AXIS_STEP) printf("[F] Y_AXIS_STEP: %s\n", data & Y_AXIS_STEP ? "HIGH" : "LOW");
+ if(changed & Y_AXIS_EN) printf("[F] Y_AXIS_EN: %s\n", data & Y_AXIS_EN ? "HIGH" : "LOW");
+ if(changed & Y_AXIS_POT) printf("[F] Y_AXIS_POT: %s\n", data & Y_AXIS_POT ? "HIGH" : "LOW");
+#endif
+
+ m_port_f = data;
+ break;
+ }
+ case AVR8_IO_PORTG:
+ {
+ if (data == m_port_g) break;
+
+#if LOG_PORTS
+ UINT8 old_port_g = m_port_g;
+ UINT8 changed = data ^ old_port_g;
+
+ printf("[%08X] ", m_maincpu->m_shifted_pc);
+ if(changed & EX4_1280) printf("[G] EX4_1280: %s\n", data & EX4_1280 ? "HIGH" : "LOW");
+ if(changed & EX3_1280) printf("[G] EX3_1280: %s\n", data & EX3_1280 ? "HIGH" : "LOW");
+ if(changed & B_AXIS_EN) printf("[G] B_AXIS_EN: %s\n", data & B_AXIS_EN ? "HIGH" : "LOW");
+ if(changed & CUTOFF_SR_CHECK) printf("[G] CUTOFF_SR_CHECK: %s\n", data & CUTOFF_SR_CHECK ? "HIGH" : "LOW");
+ if(changed & BUZZ) printf("[G] BUZZ: %s\n", data & BUZZ ? "HIGH" : "LOW");
+#endif
+
+ m_port_g = data;
+ break;
+ }
+ case AVR8_IO_PORTH:
+ {
+ if (data == m_port_h) break;
+
+#if LOG_PORTS
+ UINT8 old_port_h = m_port_h;
+ UINT8 changed = data ^ old_port_h;
+
+ printf("[%08X] ", m_maincpu->m_shifted_pc);
+ if(changed & CUTOFF_TEST) printf("[H] CUTOFF_TEST: %s\n", data & CUTOFF_TEST ? "HIGH" : "LOW");
+ if(changed & CUTOFF_RESET) printf("[H] CUTOFF_RESET: %s\n", data & CUTOFF_RESET ? "HIGH" : "LOW");
+ if(changed & EX1_PWR_CHECK) printf("[H] EX1_PWR_CHECK: %s\n", data & EX1_PWR_CHECK ? "HIGH" : "LOW");
+ if(changed & EX1_HEAT) printf("[H] EX1_HEAT: %s\n", data & EX1_HEAT ? "HIGH" : "LOW");
+ if(changed & EX1_FAN) printf("[H] EX1_FAN: %s\n", data & EX1_FAN ? "HIGH" : "LOW");
+ if(changed & SD_WP) printf("[H] SD_WP: %s\n", data & SD_WP ? "HIGH" : "LOW");
+ if(changed & SD_CD) printf("[H] SD_CD: %s\n", data & SD_CD ? "HIGH" : "LOW");
+#endif
+
+ m_port_h = data;
+ break;
+ }
+ case AVR8_IO_PORTJ:
+ {
+ if (data == m_port_j) break;
+
+#if LOG_PORTS
+ UINT8 old_port_j = m_port_j;
+ UINT8 changed = data ^ old_port_j;
+
+ printf("[%08X] ", m_maincpu->m_shifted_pc);
+
+ if(changed & BUTTON_CENTER) printf("[J] BUTTON_CENTER: %s\n", data & BUTTON_CENTER ? "HIGH" : "LOW");
+ if(changed & BUTTON_RIGHT) printf("[J] BUTTON_RIGHT: %s\n", data & BUTTON_RIGHT ? "HIGH" : "LOW");
+ if(changed & BUTTON_LEFT) printf("[J] BUTTON_LEFT: %s\n", data & BUTTON_LEFT ? "HIGH" : "LOW");
+ if(changed & BUTTON_DOWN) printf("[J] BUTTON_DOWN: %s\n", data & BUTTON_DOWN ? "HIGH" : "LOW");
+ if(changed & BUTTON_UP) printf("[J] BUTTON_UP: %s\n", data & BUTTON_UP ? "HIGH" : "LOW");
+ if(changed & POTS_SCL) printf("[J] POTS_SCL: %s\n", data & POTS_SCL ? "HIGH" : "LOW");
+ if(changed & B_AXIS_POT) printf("[J] B_AXIS_POT: %s\n", data & B_AXIS_POT ? "HIGH" : "LOW");
+#endif
+
+ m_port_j = data;
+ break;
+ }
+ case AVR8_IO_PORTK:
+ {
+ if (data == m_port_k) break;
+
+#if LOG_PORTS
+ UINT8 old_port_k = m_port_k;
+ UINT8 changed = data ^ old_port_k;
+
+ printf("[%08X] ", m_maincpu->m_shifted_pc);
+
+ if(changed & Z_AXIS_DIR) printf("[K] Z_AXIS_DIR: %s\n", data & Z_AXIS_DIR ? "HIGH" : "LOW");
+ if(changed & Z_AXIS_STEP) printf("[K] Z_AXIS_STEP: %s\n", data & Z_AXIS_STEP ? "HIGH" : "LOW");
+ if(changed & Z_AXIS_EN) printf("[K] Z_AXIS_EN: %s\n", data & Z_AXIS_EN ? "HIGH" : "LOW");
+ if(changed & Z_AXIS_POT) printf("[K] Z_AXIS_POT: %s\n", data & Z_AXIS_POT ? "HIGH" : "LOW");
+ if(changed & EX7_1280) printf("[K] EX7_1280: %s\n", data & EX7_1280 ? "HIGH" : "LOW");
+ if(changed & EX6_1280) printf("[K] EX6_1280: %s\n", data & EX6_1280 ? "HIGH" : "LOW");
+ if(changed & EX5_1280) printf("[K] EX5_1280: %s\n", data & EX5_1280 ? "HIGH" : "LOW");
+ if(changed & HBP_THERM) printf("[K] HBP_THERM: %s\n", data & HBP_THERM ? "HIGH" : "LOW");
+#endif
+
+ m_port_k = data;
+ break;
+ }
+ case AVR8_IO_PORTL:
+ {
+ if (data == m_port_l) break;
+
+#if LOG_PORTS
+ UINT8 old_port_l = m_port_l;
+ UINT8 changed = data ^ old_port_l;
+
+ printf("[%08X] ", m_maincpu->m_shifted_pc);
+
+ if(changed & X_MIN) printf("[L] X_MIN: %s\n", data & X_MIN ? "HIGH" : "LOW");
+ if(changed & X_MAX) printf("[L] X_MAX: %s\n", data & X_MAX ? "HIGH" : "LOW");
+ if(changed & Y_MIN) printf("[L] Y_MIN: %s\n", data & Y_MIN ? "HIGH" : "LOW");
+ if(changed & Y_MAX) printf("[L] Y_MAX: %s\n", data & Y_MAX ? "HIGH" : "LOW");
+ if(changed & HBP) printf("[L] HBP: %s\n", data & HBP ? "HIGH" : "LOW");
+ if(changed & EXTRA_FET) printf("[L] EXTRA_FET: %s\n", data & EXTRA_FET ? "HIGH" : "LOW");
+ if(changed & Z_MIN) printf("[L] Z_MIN: %s\n", data & Z_MIN ? "HIGH" : "LOW");
+ if(changed & Z_MAX) printf("[L] Z_MAX: %s\n", data & Z_MAX ? "HIGH" : "LOW");
+#endif
+
+ m_port_l = data;
+ break;
+ }
+ }
+}
+
+/****************************************************\
+* Address maps *
+\****************************************************/
+
+static ADDRESS_MAP_START( replicator_prg_map, AS_PROGRAM, 8, replicator_state )
+ AM_RANGE(0x0000, 0x1FFFF) AM_ROM
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START( replicator_data_map, AS_DATA, 8, replicator_state )
+ AM_RANGE(0x0200, 0x21FF) AM_RAM /* ATMEGA1280 Internal SRAM */
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START( replicator_io_map, AS_IO, 8, replicator_state )
+ AM_RANGE(AVR8_IO_PORTA, AVR8_IO_PORTL) AM_READWRITE( port_r, port_w )
+ADDRESS_MAP_END
+
+/****************************************************\
+* Input ports *
+\****************************************************/
+
+static INPUT_PORTS_START( replicator )
+ PORT_START("keypad")
+ PORT_BIT(0x00000001, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("CENTER") PORT_CODE(KEYCODE_M)
+ PORT_BIT(0x00000002, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("RIGHT") PORT_CODE(KEYCODE_D)
+ PORT_BIT(0x00000004, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("LEFT") PORT_CODE(KEYCODE_A)
+ PORT_BIT(0x00000008, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("DOWN") PORT_CODE(KEYCODE_S)
+ PORT_BIT(0x00000010, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("UP") PORT_CODE(KEYCODE_W)
+INPUT_PORTS_END
+
+/****************************************************\
+* Machine definition *
+\****************************************************/
+
+DRIVER_INIT_MEMBER(replicator_state, replicator)
+{
+}
+
+void replicator_state::machine_reset()
+{
+ shift_register_value = 0;
+ m_port_a = 0;
+ m_port_b = 0;
+ m_port_c = 0;
+ m_port_d = 0;
+ m_port_e = 0;
+ m_port_f = 0;
+ m_port_g = 0;
+ m_port_h = 0;
+ m_port_j = 0;
+ m_port_k = 0;
+ m_port_l = 0;
+}
+
+const avr8_config atmega1280_config =
+{
+ "eeprom"
+};
+
+void replicator_state::palette_init()
+{
+//These colors were picked with the color picker in Inkscape, based on a photo of the LCD used in the Replicator 1 3d printer:
+ palette_set_color(machine(), 0, MAKE_RGB(0xCA, 0xE7, 0xEB));
+ palette_set_color(machine(), 1, MAKE_RGB(0x78, 0xAB, 0xA8));
+}
+
+static const gfx_layout hd44780_charlayout =
+{
+ 5, 8, /* 5 x 8 characters */
+ 256, /* 256 characters */
+ 1, /* 1 bits per pixel */
+ { 0 }, /* no bitplanes */
+ { 3, 4, 5, 6, 7},
+ { 0, 8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8},
+ 8*8 /* 8 bytes */
+};
+
+static GFXDECODE_START( replicator )
+ GFXDECODE_ENTRY( "hd44780:cgrom", 0x0000, hd44780_charlayout, 0, 1 )
+GFXDECODE_END
+
+static MACHINE_CONFIG_START( replicator, replicator_state )
+
+ MCFG_CPU_ADD("maincpu", ATMEGA1280, MASTER_CLOCK)
+ MCFG_CPU_AVR8_CONFIG(atmega1280_config)
+ MCFG_CPU_PROGRAM_MAP(replicator_prg_map)
+ MCFG_CPU_DATA_MAP(replicator_data_map)
+ MCFG_CPU_IO_MAP(replicator_io_map)
+
+ MCFG_CPU_AVR8_LFUSE(0xFF)
+ MCFG_CPU_AVR8_HFUSE(0xDA)
+ MCFG_CPU_AVR8_EFUSE(0xF4)
+ MCFG_CPU_AVR8_LOCK(0x0F)
+
+ /*TODO: Add an ATMEGA8U2 for USB-Serial communications */
+
+ /* video hardware */
+ MCFG_SCREEN_ADD("screen", LCD)
+ MCFG_SCREEN_REFRESH_RATE(50)
+ MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500)) /* not accurate */
+ MCFG_SCREEN_UPDATE_DEVICE("hd44780", hd44780_device, screen_update)
+ MCFG_SCREEN_SIZE(120, 18*2) //4x20 chars
+ MCFG_SCREEN_VISIBLE_AREA(0, 120-1, 0, 18*2-1)
+
+ MCFG_PALETTE_LENGTH(2)
+ MCFG_GFXDECODE(replicator)
+ MCFG_DEFAULT_LAYOUT(layout_lcd)
+
+ MCFG_HD44780_ADD("hd44780")
+ MCFG_HD44780_LCD_SIZE(4, 20)
+
+ /*TODO:
+ Add sound config:
+ - A buzzer connected to the PG5 pin that is driven by Timer/Counter #4
+ */
+
+MACHINE_CONFIG_END
+
+ROM_START( replica1 )
+ ROM_REGION( 0x20000, "maincpu", 0 ) /* Main program store */
+ ROM_LOAD( "mighty_one_v7.5.0.bin", 0x0000, 0x1EF9A, CRC(0d36d9e7) SHA1(a53899775b4c4eea87b6903758ebb75f06710a69) ) /*Sailfish firmware image - Metamaquian build v7.5 */
+ ROM_LOAD( "atmegaboot_168_atmega1280.bin", 0x1F000, 0x0F16, CRC(c041f8db) SHA1(d995ebf360a264cccacec65f6dc0c2257a3a9224) ) /*Arduino MEGA bootloader*/
+
+ ROM_REGION( 0x1000, "eeprom", ROMREGION_ERASEFF ) /* on-die 4kbyte eeprom */
+ //ROM_LOAD( "eeprom.raw", 0x0000, 0x1000, CRC(c71c0011) SHA1(1ceaf73df40e531df3bfb26b4fb7cd95fb7bff1d) ) /* blank EEPROM data */
+ROM_END
+
+/* YEAR NAME PARENT COMPAT MACHINE INPUT INIT COMPANY FULLNAME */
+CONS(2012, replica1, 0, 0, replicator, replicator, replicator_state, replicator, "Makerbot", "Replicator 1 desktop 3d printer", GAME_NOT_WORKING|GAME_NO_SOUND)
diff --git a/src/mess/mess.lst b/src/mess/mess.lst
index 81126325205..9bd56a4a377 100644
--- a/src/mess/mess.lst
+++ b/src/mess/mess.lst
@@ -309,6 +309,9 @@ wofch // CPS Changer (Tenchi Wo Kurau II)
odyssey2 // Magnavox Odyssey 2 - 1978-1983
odyssey3 // Magnavox Odyssey 3 / Command Center (prototype)
+// Makerbot
+replica1 // Makerbot Replicator 1 desktop 3d printer
+
// Hartung, Watara, ...
gmaster // Hartung Gamemaster
diff --git a/src/mess/mess.mak b/src/mess/mess.mak
index e2309604a3a..d6207f4e0e1 100644
--- a/src/mess/mess.mak
+++ b/src/mess/mess.mak
@@ -598,6 +598,7 @@ DRVLIBS += \
$(MESSOBJ)/kyocera.a \
$(MESSOBJ)/luxor.a \
$(MESSOBJ)/magnavox.a \
+ $(MESSOBJ)/makerbot.a \
$(MESSOBJ)/matsushi.a \
$(MESSOBJ)/mattel.a \
$(MESSOBJ)/mb.a \
@@ -1398,6 +1399,9 @@ $(MESSOBJ)/luxor.a: \
$(MESSOBJ)/magnavox.a: \
$(MESS_DRIVERS)/odyssey2.o \
+$(MESSOBJ)/makerbot.a: \
+ $(MESS_DRIVERS)/replicator.o \
+
$(MESSOBJ)/mattel.a: \
$(MESS_DRIVERS)/aquarius.o \
$(MESS_VIDEO)/aquarius.o \
diff --git a/src/targets/mess.lst b/src/targets/mess.lst
index 86c75733479..51d297f2636 100644
--- a/src/targets/mess.lst
+++ b/src/targets/mess.lst
@@ -399,6 +399,9 @@
@magnavox
/mess/drivers/odyssey2
+@makerbot
+/mess/drivers/replicator
+
@mattel
/mess/drivers/aquarius
/mess/drivers/juicebox