summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/avr8/avr8.cpp
diff options
context:
space:
mode:
author Ryan Holtz <ryan.holtz@arrowheadgs.com>2020-10-31 18:51:36 +0100
committer Ryan Holtz <ryan.holtz@arrowheadgs.com>2020-10-31 18:52:06 +0100
commitc9d3d973dd955bc985346f3ef3cad77246ed753c (patch)
treec2293b47c3ab705dc049f8ade418df74cf0d5de7 /src/devices/cpu/avr8/avr8.cpp
parent36961e3e5febfa707ca79b510331a3f8596208ec (diff)
-avr8: Converted from using an IO address space to devcb for GPIO I/O. [Ryan Holtz]
Diffstat (limited to 'src/devices/cpu/avr8/avr8.cpp')
-rw-r--r--src/devices/cpu/avr8/avr8.cpp149
1 files changed, 84 insertions, 65 deletions
diff --git a/src/devices/cpu/avr8/avr8.cpp b/src/devices/cpu/avr8/avr8.cpp
index de75492ee7d..b98f2ec9bf1 100644
--- a/src/devices/cpu/avr8/avr8.cpp
+++ b/src/devices/cpu/avr8/avr8.cpp
@@ -711,7 +711,6 @@ avr8_device::avr8_device(const machine_config &mconfig, const char *tag, device_
, m_shifted_pc(0)
, m_program_config("program", ENDIANNESS_LITTLE, 8, 22)
, m_data_config("data", ENDIANNESS_LITTLE, 8, 16, 0, internal_map)
- , m_io_config("io", ENDIANNESS_LITTLE, 8, 4)
, m_eeprom(*this, finder_base::DUMMY_TAG)
, m_lfuses(0x62)
, m_hfuses(0x99)
@@ -719,6 +718,8 @@ avr8_device::avr8_device(const machine_config &mconfig, const char *tag, device_
, m_lock_bits(0xff)
, m_pc(0)
, m_num_timers(num_timers)
+ , m_gpio_out_cb(*this)
+ , m_gpio_in_cb(*this)
, m_spi_active(false)
, m_spi_prescale(0)
, m_spi_prescale_count(0)
@@ -813,7 +814,9 @@ void avr8_device::device_start()
m_program = &space(AS_PROGRAM);
m_data = &space(AS_DATA);
- m_io = &space(AS_IO);
+
+ m_gpio_out_cb.resolve_all_safe();
+ m_gpio_in_cb.resolve_all_safe(0);
// register our state for the debugger
state_add(STATE_GENPC, "GENPC", m_shifted_pc).noshow();
@@ -992,8 +995,7 @@ device_memory_interface::space_config_vector avr8_device::memory_space_config()
{
return space_config_vector {
std::make_pair(AS_PROGRAM, &m_program_config),
- std::make_pair(AS_DATA, &m_data_config),
- std::make_pair(AS_IO, &m_io_config)
+ std::make_pair(AS_DATA, &m_data_config)
};
}
@@ -1226,7 +1228,7 @@ void avr8_device::timer_tick()
{
uint8_t out_bit = (m_r[AVR8_REGIDX_SPDR] & (1 << m_spi_prescale_countdown)) >> m_spi_prescale_countdown;
m_spi_prescale_countdown--;
- m_io->write_byte(AVR8_IO_PORTB, (m_r[AVR8_REGIDX_PORTB] &~ AVR8_PORTB_MOSI) | (out_bit ? AVR8_PORTB_MOSI : 0));
+ write_gpio(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;
}
@@ -1299,7 +1301,7 @@ void avr8_device::timer0_tick()
{
m_timer_top[0] = 0;
LOGMASKED(LOG_TIMER0, "%s: timer0: Toggle OC0B on match\n", machine().describe_context());
- m_io->write_byte(AVR8_IO_PORTG, m_io->read_byte(AVR8_IO_PORTG) ^ (1 << 5));
+ write_gpio(AVR8_IO_PORTG, m_r[AVR8_REGIDX_PORTG] ^ (1 << 5));
}
break;
@@ -1308,7 +1310,7 @@ void avr8_device::timer0_tick()
{
m_timer_top[0] = 0;
LOGMASKED(LOG_TIMER0, "[0] timer0: Clear OC0B on match\n", machine().describe_context());
- m_io->write_byte(AVR8_IO_PORTG, m_io->read_byte(AVR8_IO_PORTG) & ~(1 << 5));
+ write_gpio(AVR8_IO_PORTG, m_r[AVR8_REGIDX_PORTG] & ~(1 << 5));
}
break;
@@ -1317,7 +1319,7 @@ void avr8_device::timer0_tick()
{
m_timer_top[0] = 0;
LOGMASKED(LOG_TIMER0, "%s: timer0: Set OC0B on match\n", machine().describe_context());
- m_io->write_byte(AVR8_IO_PORTG, m_io->read_byte(AVR8_IO_PORTG) | (1 << 5));
+ write_gpio(AVR8_IO_PORTG, m_r[AVR8_REGIDX_PORTG] | (1 << 5));
}
break;
}
@@ -1443,18 +1445,18 @@ inline void avr8_device::timer1_tick()
if (reg == 0)
{
LOGMASKED(LOG_TIMER1, "%s: timer1: Toggle OC1%c on match\n", machine().describe_context());
- m_io->write_byte(AVR8_IO_PORTB, m_io->read_byte(AVR8_IO_PORTB) ^ (2 << reg));
+ write_gpio(AVR8_IO_PORTB, read_gpio(AVR8_REGIDX_PORTB) ^ (2 << reg));
}
break;
case 2: /* Clear OC1A/B on compare match */
LOGMASKED(LOG_TIMER1, "%s: timer1: Clear OC1%c on match\n", machine().describe_context(), reg ? 'B' : 'A');
- m_io->write_byte(AVR8_IO_PORTB, m_io->read_byte(AVR8_IO_PORTB) & ~(2 << reg));
+ write_gpio(AVR8_IO_PORTB, read_gpio(AVR8_REGIDX_PORTB) & ~(2 << reg));
break;
case 3: /* Set OC1A/B on compare match */
LOGMASKED(LOG_TIMER1, "%s: timer1: Set OC1%c on match\n", machine().describe_context(), reg ? 'B' : 'A');
- m_io->write_byte(AVR8_IO_PORTB, m_io->read_byte(AVR8_IO_PORTB) | (2 << reg));
+ write_gpio(AVR8_IO_PORTB, read_gpio(AVR8_REGIDX_PORTB) | (2 << reg));
break;
}
@@ -1491,18 +1493,18 @@ inline void avr8_device::timer1_tick()
if (reg == 0)
{
LOGMASKED(LOG_TIMER1, "%s: timer1: Toggle OC1%c on match\n", machine().describe_context());
- m_io->write_byte(AVR8_IO_PORTB, m_io->read_byte(AVR8_IO_PORTB) ^ (2 << reg));
+ write_gpio(AVR8_IO_PORTB, m_r[AVR8_REGIDX_PORTB] ^ (2 << reg));
}
break;
case 2: /* Clear OC1A/B on compare match */
LOGMASKED(LOG_TIMER1, "%s: timer1: Clear OC1%c on match\n", machine().describe_context(), reg ? 'B' : 'A');
- m_io->write_byte(AVR8_IO_PORTB, m_io->read_byte(AVR8_IO_PORTB) & ~(2 << reg));
+ write_gpio(AVR8_IO_PORTB, m_r[AVR8_REGIDX_PORTB] & ~(2 << reg));
break;
case 3: /* Set OC1A/B on compare match */
LOGMASKED(LOG_TIMER1, "%s: timer1: Set OC1%c on match\n", machine().describe_context(), reg ? 'B' : 'A');
- m_io->write_byte(AVR8_IO_PORTB, m_io->read_byte(AVR8_IO_PORTB) | (2 << reg));
+ write_gpio(AVR8_IO_PORTB, m_r[AVR8_REGIDX_PORTB] | (2 << reg));
break;
}
@@ -1526,18 +1528,18 @@ inline void avr8_device::timer1_tick()
if (reg == 0)
{
LOGMASKED(LOG_TIMER1, "%s: timer1: Toggle OC1A at BOTTOM\n", machine().describe_context());
- m_io->write_byte(AVR8_IO_PORTB, m_io->read_byte(AVR8_IO_PORTB) ^ (2 << reg));
+ write_gpio(AVR8_IO_PORTB, m_r[AVR8_REGIDX_PORTB] ^ (2 << reg));
}
break;
case 2: /* Set OC1A/B at BOTTOM*/
LOGMASKED(LOG_TIMER1, "%s: timer1: Set OC1%c at BOTTOM\n", machine().describe_context(), reg ? 'B' : 'A');
- m_io->write_byte(AVR8_IO_PORTB, m_io->read_byte(AVR8_IO_PORTB) | (2 << reg));
+ write_gpio(AVR8_IO_PORTB, m_r[AVR8_REGIDX_PORTB] | (2 << reg));
break;
case 3: /* Clear OC1A/B at BOTTOM */
LOGMASKED(LOG_TIMER1, "%s: timer1: Clear OC1%c at BOTTOM\n", machine().describe_context(), reg ? 'B' : 'A');
- m_io->write_byte(AVR8_IO_PORTB, m_io->read_byte(AVR8_IO_PORTB) & ~(2 << reg));
+ write_gpio(AVR8_IO_PORTB, m_r[AVR8_REGIDX_PORTB] & ~(2 << reg));
break;
}
}
@@ -1555,18 +1557,18 @@ inline void avr8_device::timer1_tick()
if (reg == 0)
{
LOGMASKED(LOG_TIMER1, "%s: timer1: Toggle OC1%c on match\n", machine().describe_context());
- m_io->write_byte(AVR8_IO_PORTB, m_io->read_byte(AVR8_IO_PORTB) ^ (2 << reg));
+ write_gpio(AVR8_IO_PORTB, m_r[AVR8_REGIDX_PORTB] ^ (2 << reg));
}
break;
case 2: /* Clear OC1A/B on compare match */
LOGMASKED(LOG_TIMER1, "%s: timer1: Clear OC1%c on match\n", machine().describe_context(), reg ? 'B' : 'A');
- m_io->write_byte(AVR8_IO_PORTB, m_io->read_byte(AVR8_IO_PORTB) & ~(2 << reg));
+ write_gpio(AVR8_IO_PORTB, m_r[AVR8_REGIDX_PORTB] & ~(2 << reg));
break;
case 3: /* Set OC1A/B on compare match */
LOGMASKED(LOG_TIMER1, "%s: timer1: Set OC1%c on match\n", machine().describe_context(), reg ? 'B' : 'A');
- m_io->write_byte(AVR8_IO_PORTB, m_io->read_byte(AVR8_IO_PORTB) | (2 << reg));
+ write_gpio(AVR8_IO_PORTB, m_r[AVR8_REGIDX_PORTB] | (2 << reg));
break;
}
@@ -1590,18 +1592,18 @@ inline void avr8_device::timer1_tick()
if (reg == 0)
{
LOGMASKED(LOG_TIMER1, "%s: timer1: Toggle OC1A at BOTTOM\n", machine().describe_context());
- m_io->write_byte(AVR8_IO_PORTB, m_io->read_byte(AVR8_IO_PORTB) ^ (2 << reg));
+ write_gpio(AVR8_IO_PORTB, m_r[AVR8_REGIDX_PORTB] ^ (2 << reg));
}
break;
case 2: /* Set OC1A/B at BOTTOM*/
LOGMASKED(LOG_TIMER1, "%s: timer1: Set OC1%c at BOTTOM\n", machine().describe_context(), reg ? 'B' : 'A');
- m_io->write_byte(AVR8_IO_PORTB, m_io->read_byte(AVR8_IO_PORTB) | (2 << reg));
+ write_gpio(AVR8_IO_PORTB, m_r[AVR8_REGIDX_PORTB] | (2 << reg));
break;
case 3: /* Clear OC1A/B at BOTTOM */
LOGMASKED(LOG_TIMER1, "%s: timer1: Clear OC1%c at BOTTOM\n", machine().describe_context(), reg ? 'B' : 'A');
- m_io->write_byte(AVR8_IO_PORTB, m_io->read_byte(AVR8_IO_PORTB) & ~(2 << reg));
+ write_gpio(AVR8_IO_PORTB, m_r[AVR8_REGIDX_PORTB] & ~(2 << reg));
break;
}
}
@@ -1795,7 +1797,7 @@ void avr8_device::timer2_tick()
if (count >= 0xff)
{
// Turn on
- m_io->write_byte(AVR8_IO_PORTD, m_io->read_byte(AVR8_IO_PORTD) | (1 << 7));
+ write_gpio(AVR8_IO_PORTD, m_r[AVR8_REGIDX_PORTD] | (1 << 7));
m_r[AVR8_REGIDX_TCNT2] = 0;
m_ocr2_not_reached_yet = true;
}
@@ -1804,7 +1806,7 @@ void avr8_device::timer2_tick()
if (m_ocr2_not_reached_yet)
{
// Turn off
- m_io->write_byte(AVR8_IO_PORTD, m_io->read_byte(AVR8_IO_PORTD) & ~(1 << 7));
+ write_gpio(AVR8_IO_PORTD, m_r[AVR8_REGIDX_PORTD] & ~(1 << 7));
m_ocr2_not_reached_yet = false;
}
}
@@ -1945,13 +1947,13 @@ void avr8_device::timer4_tick()
{
// Clear OC0B
LOGMASKED(LOG_TIMER4, "%s: timer4: non-inverting mode, Clear OC0B\n", machine().describe_context());
- m_io->write_byte(AVR8_IO_PORTG, m_io->read_byte(AVR8_IO_PORTG) & ~(1 << 5));
+ write_gpio(AVR8_IO_PORTG, m_r[AVR8_REGIDX_PORTG] & ~(1 << 5));
}
else if (count == 0)
{
// Set OC0B
LOGMASKED(LOG_TIMER4, "%s: timer4: non-inverting mode, Set OC0B\n", machine().describe_context());
- m_io->write_byte(AVR8_IO_PORTG, m_io->read_byte(AVR8_IO_PORTG) | (1 << 5));
+ write_gpio(AVR8_IO_PORTG, m_r[AVR8_REGIDX_PORTG] | (1 << 5));
}
break;
case 3: /* Inverting mode */
@@ -1959,13 +1961,13 @@ void avr8_device::timer4_tick()
{
// Set OC0B
LOGMASKED(LOG_TIMER4, "%s: timer4: inverting mode, Clear OC0B\n", machine().describe_context());
- m_io->write_byte(AVR8_IO_PORTG, m_io->read_byte(AVR8_IO_PORTG) | (1 << 5));
+ write_gpio(AVR8_IO_PORTG, m_r[AVR8_REGIDX_PORTG] | (1 << 5));
}
else if (count == 0)
{
// Clear OC0B
LOGMASKED(LOG_TIMER4, "%s: timer4: inverting mode, Set OC0B\n", machine().describe_context());
- m_io->write_byte(AVR8_IO_PORTG, m_io->read_byte(AVR8_IO_PORTG) & ~(1 << 5));
+ write_gpio(AVR8_IO_PORTG, m_r[AVR8_REGIDX_PORTG] & ~(1 << 5));
}
break;
}
@@ -2144,7 +2146,7 @@ void avr8_device::timer5_tick()
{
m_timer_top[5] = 0;
LOGMASKED(LOG_TIMER5, "%s: timer5: Toggle OC5B on compare match\n", machine().describe_context());
- m_io->write_byte(AVR8_IO_PORTL, m_io->read_byte(AVR8_IO_PORTL) ^ (1 << 4));
+ write_gpio(AVR8_IO_PORTL, m_r[AVR8_REGIDX_PORTL] ^ (1 << 4));
}
break;
case 2: /* Clear OC5B on compare match */
@@ -2153,7 +2155,7 @@ void avr8_device::timer5_tick()
m_timer_top[5] = 0;
// Clear OC5B
LOGMASKED(LOG_TIMER5, "%s: timer5: Clear OC5B on compare match\n", machine().describe_context());
- m_io->write_byte(AVR8_IO_PORTL, m_io->read_byte(AVR8_IO_PORTL) & ~(1 << 4));
+ write_gpio(AVR8_IO_PORTL, m_r[AVR8_REGIDX_PORTL] & ~(1 << 4));
}
break;
case 3: /* Set OC5B on compare match */
@@ -2161,7 +2163,7 @@ void avr8_device::timer5_tick()
{
m_timer_top[5] = 0;
LOGMASKED(LOG_TIMER5, "%s: timer5: Set OC5B on compare match\n", machine().describe_context());
- m_io->write_byte(AVR8_IO_PORTL, m_io->read_byte(AVR8_IO_PORTL) | (1 << 4));
+ write_gpio(AVR8_IO_PORTL, m_r[AVR8_REGIDX_PORTL] | (1 << 4));
}
break;
}
@@ -2335,6 +2337,34 @@ void avr8_device::change_spsr(uint8_t data)
/*****************************************************************************/
+void avr8_device::write_gpio(const uint8_t port, const uint8_t data)
+{
+ static const uint16_t s_port_to_reg[11] =
+ {
+ AVR8_REGIDX_PORTA,
+ AVR8_REGIDX_PORTB,
+ AVR8_REGIDX_PORTC,
+ AVR8_REGIDX_PORTD,
+ AVR8_REGIDX_PORTE,
+ AVR8_REGIDX_PORTF,
+ AVR8_REGIDX_PORTG,
+ AVR8_REGIDX_PORTH,
+ AVR8_REGIDX_PORTJ,
+ AVR8_REGIDX_PORTK,
+ AVR8_REGIDX_PORTL
+ };
+
+ m_r[s_port_to_reg[port]] = data;
+ m_gpio_out_cb[port](data);
+}
+
+uint8_t avr8_device::read_gpio(const uint8_t port)
+{
+ return m_gpio_in_cb[port]();
+}
+
+/*****************************************************************************/
+
void avr8_device::regs_w(offs_t offset, uint8_t data)
{
switch (offset)
@@ -2376,68 +2406,57 @@ void avr8_device::regs_w(offs_t offset, uint8_t data)
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;
+ write_gpio(AVR8_IO_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;
+ write_gpio(AVR8_IO_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;
+ write_gpio(AVR8_IO_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;
+ write_gpio(AVR8_IO_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;
+ write_gpio(AVR8_IO_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;
+ write_gpio(AVR8_IO_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;
+ write_gpio(AVR8_IO_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;
+ write_gpio(AVR8_IO_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;
+ write_gpio(AVR8_IO_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;
+ write_gpio(AVR8_IO_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;
+ write_gpio(AVR8_IO_PORTL, data);
break;
case AVR8_REGIDX_DDRA:
@@ -2994,47 +3013,47 @@ uint8_t avr8_device::regs_r(offs_t offset)
case AVR8_REGIDX_PINA:
// TODO: account for DDRA
- return m_io->read_byte(AVR8_REG_A);
+ return read_gpio(AVR8_IO_PORTA);
case AVR8_REGIDX_PINB:
// TODO: account for DDRB
- return m_io->read_byte(AVR8_REG_B);
+ return read_gpio(AVR8_IO_PORTB);
case AVR8_REGIDX_PINC:
// TODO: account for DDRC
- return m_io->read_byte(AVR8_REG_C);
+ return read_gpio(AVR8_IO_PORTC);
case AVR8_REGIDX_PIND:
// TODO: account for DDRD
- return m_io->read_byte(AVR8_REG_D);
+ return read_gpio(AVR8_IO_PORTD);
case AVR8_REGIDX_PINE:
// TODO: account for DDRE
- return m_io->read_byte(AVR8_REG_E);
+ return read_gpio(AVR8_IO_PORTE);
case AVR8_REGIDX_PINF:
// TODO: account for DDRF
- return m_io->read_byte(AVR8_REG_F);
+ return read_gpio(AVR8_IO_PORTF);
case AVR8_REGIDX_PING:
// TODO: account for DDRG
- return m_io->read_byte(AVR8_REG_G);
+ return read_gpio(AVR8_IO_PORTG);
case AVR8_REGIDX_PINH:
// TODO: account for DDRH
- return m_io->read_byte(AVR8_REG_H);
+ return read_gpio(AVR8_IO_PORTH);
case AVR8_REGIDX_PINJ:
// TODO: account for DDRJ
- return m_io->read_byte(AVR8_REG_J);
+ return read_gpio(AVR8_IO_PORTJ);
case AVR8_REGIDX_PINK:
// TODO: account for DDRK
- return m_io->read_byte(AVR8_REG_K);
+ return read_gpio(AVR8_IO_PORTK);
case AVR8_REGIDX_PINL:
// TODO: account for DDRL
- return m_io->read_byte(AVR8_REG_L);
+ return read_gpio(AVR8_IO_PORTL);
case AVR8_REGIDX_PORTA:
case AVR8_REGIDX_PORTB: