diff options
Diffstat (limited to 'src/devices/machine/6532riot.cpp')
-rw-r--r-- | src/devices/machine/6532riot.cpp | 515 |
1 files changed, 0 insertions, 515 deletions
diff --git a/src/devices/machine/6532riot.cpp b/src/devices/machine/6532riot.cpp deleted file mode 100644 index f24b8b1656c..00000000000 --- a/src/devices/machine/6532riot.cpp +++ /dev/null @@ -1,515 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Aaron Giles -/*************************************************************************** - - RIOT 6532 emulation - -The timer seems to follow these rules: -- When the timer flag changes from 0 to 1 the timer continues to count - down at a 1 cycle rate. -- When the timer is being read or written the timer flag is reset. -- When the timer flag is set and the timer contents are 0, the counting - stops. - -***************************************************************************/ - -#include "emu.h" -#include "6532riot.h" - - -//************************************************************************** -// CONSTANTS -//************************************************************************** - -// device type definition -DEFINE_DEVICE_TYPE(RIOT6532, riot6532_device, "riot6532", "6532 RIOT") - -enum -{ - TIMER_IDLE, - TIMER_COUNTING, - TIMER_FINISHING -}; - -#define TIMER_FLAG 0x80 -#define PA7_FLAG 0x40 - - - -/*************************************************************************** - INTERNAL FUNCTIONS -***************************************************************************/ - -/*------------------------------------------------- - update_irqstate - update the IRQ state - based on interrupt enables --------------------------------------------------*/ - -void riot6532_device::update_irqstate() -{ - int irq = (m_irqstate & m_irqenable) ? ASSERT_LINE : CLEAR_LINE; - - if (m_irq != irq) - { - m_irq_cb(irq); - m_irq = irq; - } -} - - -/*------------------------------------------------- - apply_ddr - combine inputs and outputs - according to the DDR --------------------------------------------------*/ - -uint8_t riot6532_device::apply_ddr(const riot6532_port *port) -{ - return (port->m_out & port->m_ddr) | (port->m_in & ~port->m_ddr); -} - - -/*------------------------------------------------- - update_pa7_state - see if PA7 has changed - and signal appropriately --------------------------------------------------*/ - -void riot6532_device::update_pa7_state() -{ - uint8_t data = apply_ddr(&m_port[0]) & 0x80; - - /* if the state changed in the correct direction, set the PA7 flag and update IRQs */ - if ((m_pa7prev ^ data) && (m_pa7dir ^ data) == 0) - { - m_irqstate |= PA7_FLAG; - update_irqstate(); - } - m_pa7prev = data; -} - - -/*------------------------------------------------- - get_timer - return the current timer value --------------------------------------------------*/ - -uint8_t riot6532_device::get_timer() -{ - /* if idle, return 0 */ - if (m_timerstate == TIMER_IDLE) - { - return 0; - } - - /* if counting, return the number of ticks remaining */ - else if (m_timerstate == TIMER_COUNTING) - { - return m_timer->remaining().as_ticks(clock()) >> m_timershift; - } - - /* if finishing, return the number of ticks without the shift */ - else - { - return m_timer->remaining().as_ticks(clock()); - } -} - - - -void riot6532_device::timer_end() -{ - assert(m_timerstate != TIMER_IDLE); - - /* if we finished counting, switch to the finishing state */ - if(m_timerstate == TIMER_COUNTING) - { - m_timerstate = TIMER_FINISHING; - m_timer->adjust(attotime::from_ticks(256, clock())); - - /* signal timer IRQ as well */ - m_irqstate |= TIMER_FLAG; - update_irqstate(); - } - - /* if we finished finishing, keep spinning */ - else if (m_timerstate == TIMER_FINISHING) - { - m_timer->adjust(attotime::from_ticks(256, clock())); - } -} - - - -/*************************************************************************** - I/O ACCESS -***************************************************************************/ - -/*------------------------------------------------- - riot6532_w - master I/O write access --------------------------------------------------*/ - -WRITE8_MEMBER( riot6532_device::write ) -{ - reg_w(offset, data); -} - -void riot6532_device::reg_w(uint8_t offset, uint8_t data) -{ - /* if A4 == 1 and A2 == 1, we are writing to the timer */ - if ((offset & 0x14) == 0x14) - { - static const uint8_t timershift[4] = { 0, 3, 6, 10 }; - attotime curtime = machine().time(); - int64_t target; - - /* A0-A1 contain the timer divisor */ - m_timershift = timershift[offset & 3]; - - /* A3 contains the timer IRQ enable */ - if (offset & 8) - m_irqenable |= TIMER_FLAG; - else - m_irqenable &= ~TIMER_FLAG; - - /* writes here clear the timer flag */ - if (m_timerstate != TIMER_FINISHING || get_timer() != 0xff) - { - m_irqstate &= ~TIMER_FLAG; - } - update_irqstate(); - - /* update the timer */ - m_timerstate = TIMER_COUNTING; - target = curtime.as_ticks(clock()) + 1 + (data << m_timershift); - m_timer->adjust(attotime::from_ticks(target, clock()) - curtime); - } - - /* if A4 == 0 and A2 == 1, we are writing to the edge detect control */ - else if ((offset & 0x14) == 0x04) - { - /* A1 contains the A7 IRQ enable */ - if (offset & 2) - { - m_irqenable |= PA7_FLAG; - } - else - { - m_irqenable &= ~PA7_FLAG; - } - - /* A0 specifies the edge detect direction: 0=negative, 1=positive */ - m_pa7dir = (offset & 1) << 7; - } - - /* if A4 == anything and A2 == 0, we are writing to the I/O section */ - else - { - /* A1 selects the port */ - riot6532_port *port = &m_port[BIT(offset, 1)]; - - /* if A0 == 1, we are writing to the port's DDR */ - if (offset & 1) - { - port->m_ddr = data; - } - - /* if A0 == 0, we are writing to the port's output */ - else - { - port->m_out = data; - (*port->m_out_cb)((offs_t)0, data); - } - - /* writes to port A need to update the PA7 state */ - if (port == &m_port[0]) - { - update_pa7_state(); - } - } -} - - -/*------------------------------------------------- - riot6532_r - master I/O read access --------------------------------------------------*/ - -READ8_MEMBER( riot6532_device::read ) -{ - return reg_r(offset, machine().side_effects_disabled()); -} - -uint8_t riot6532_device::reg_r(uint8_t offset, bool debugger_access) -{ - uint8_t val; - - /* if A2 == 1 and A0 == 1, we are reading interrupt flags */ - if ((offset & 0x05) == 0x05) - { - val = m_irqstate; - - if ( ! debugger_access ) - { - /* implicitly clears the PA7 flag */ - m_irqstate &= ~PA7_FLAG; - update_irqstate(); - } - } - - /* if A2 == 1 and A0 == 0, we are reading the timer */ - else if ((offset & 0x05) == 0x04) - { - val = get_timer(); - - if ( ! debugger_access ) - { - /* A3 contains the timer IRQ enable */ - if (offset & 8) - { - m_irqenable |= TIMER_FLAG; - } - else - { - m_irqenable &= ~TIMER_FLAG; - } - - /* implicitly clears the timer flag */ - if (m_timerstate != TIMER_FINISHING || val != 0xff) - { - m_irqstate &= ~TIMER_FLAG; - } - update_irqstate(); - } - } - - /* if A2 == 0 and A0 == anything, we are reading from ports */ - else - { - /* A1 selects the port */ - riot6532_port *port = &m_port[BIT(offset, 1)]; - - /* if A0 == 1, we are reading the port's DDR */ - if (offset & 1) - { - val = port->m_ddr; - } - - /* if A0 == 0, we are reading the port as an input */ - else - { - /* call the input callback if it exists */ - if (!(*port->m_in_cb).isnull()) - { - port->m_in = (*port->m_in_cb)(0); - - /* changes to port A need to update the PA7 state */ - if (port == &m_port[0]) - { - if (!debugger_access) - { - update_pa7_state(); - } - } - } - - /* apply the DDR to the result */ - val = apply_ddr(port); - } - } - return val; -} - - -/*------------------------------------------------- - porta_in_set - set port A input value --------------------------------------------------*/ - -void riot6532_device::porta_in_set(uint8_t data, uint8_t mask) -{ - m_port[0].m_in = (m_port[0].m_in & ~mask) | (data & mask); - update_pa7_state(); -} - - -/*------------------------------------------------- - portb_in_set - set port B input value --------------------------------------------------*/ - -void riot6532_device::portb_in_set(uint8_t data, uint8_t mask) -{ - m_port[1].m_in = (m_port[1].m_in & ~mask) | (data & mask); -} - - -/*------------------------------------------------- - porta_in_get - return port A input value --------------------------------------------------*/ - -uint8_t riot6532_device::porta_in_get() -{ - return m_port[0].m_in; -} - - -/*------------------------------------------------- - portb_in_get - return port B input value --------------------------------------------------*/ - -uint8_t riot6532_device::portb_in_get() -{ - return m_port[1].m_in; -} - - -/*------------------------------------------------- - porta_in_get - return port A output value --------------------------------------------------*/ - -uint8_t riot6532_device::porta_out_get() -{ - return m_port[0].m_out; -} - - -/*------------------------------------------------- - portb_in_get - return port B output value --------------------------------------------------*/ - -uint8_t riot6532_device::portb_out_get() -{ - return m_port[1].m_out; -} - - -//------------------------------------------------- -// paN_w - write Port A lines individually -//------------------------------------------------- - -WRITE_LINE_MEMBER(riot6532_device::pa0_w) { porta_in_set(state ? 0x01 : 0x00, 0x01); } -WRITE_LINE_MEMBER(riot6532_device::pa1_w) { porta_in_set(state ? 0x02 : 0x00, 0x02); } -WRITE_LINE_MEMBER(riot6532_device::pa2_w) { porta_in_set(state ? 0x04 : 0x00, 0x04); } -WRITE_LINE_MEMBER(riot6532_device::pa3_w) { porta_in_set(state ? 0x08 : 0x00, 0x08); } -WRITE_LINE_MEMBER(riot6532_device::pa4_w) { porta_in_set(state ? 0x10 : 0x00, 0x10); } -WRITE_LINE_MEMBER(riot6532_device::pa5_w) { porta_in_set(state ? 0x20 : 0x00, 0x20); } -WRITE_LINE_MEMBER(riot6532_device::pa6_w) { porta_in_set(state ? 0x40 : 0x00, 0x40); } -WRITE_LINE_MEMBER(riot6532_device::pa7_w) { porta_in_set(state ? 0x80 : 0x00, 0x80); } - -//------------------------------------------------- -// pbN_w - write Port B lines individually -//------------------------------------------------- - -WRITE_LINE_MEMBER(riot6532_device::pb0_w) { portb_in_set(state ? 0x01 : 0x00, 0x01); } -WRITE_LINE_MEMBER(riot6532_device::pb1_w) { portb_in_set(state ? 0x02 : 0x00, 0x02); } -WRITE_LINE_MEMBER(riot6532_device::pb2_w) { portb_in_set(state ? 0x04 : 0x00, 0x04); } -WRITE_LINE_MEMBER(riot6532_device::pb3_w) { portb_in_set(state ? 0x08 : 0x00, 0x08); } -WRITE_LINE_MEMBER(riot6532_device::pb4_w) { portb_in_set(state ? 0x10 : 0x00, 0x10); } -WRITE_LINE_MEMBER(riot6532_device::pb5_w) { portb_in_set(state ? 0x20 : 0x00, 0x20); } -WRITE_LINE_MEMBER(riot6532_device::pb6_w) { portb_in_set(state ? 0x40 : 0x00, 0x40); } -WRITE_LINE_MEMBER(riot6532_device::pb7_w) { portb_in_set(state ? 0x80 : 0x00, 0x80); } - - -//************************************************************************** -// LIVE DEVICE -//************************************************************************** - -//------------------------------------------------- -// riot6532_device - constructor -//------------------------------------------------- - -riot6532_device::riot6532_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : device_t(mconfig, RIOT6532, tag, owner, clock), - m_in_pa_cb(*this), - m_out_pa_cb(*this), - m_in_pb_cb(*this), - m_out_pb_cb(*this), - m_irq_cb(*this), - m_irqstate(0), - m_irqenable(0), - m_irq(CLEAR_LINE), - m_pa7dir(0), - m_pa7prev(0), - m_timershift(0), - m_timerstate(0), - m_timer(nullptr) -{ - memset(m_port, 0x00, sizeof(m_port)); -} - -/*------------------------------------------------- - device_start - device-specific startup --------------------------------------------------*/ - -void riot6532_device::device_start() -{ - /* resolve callbacks */ - m_in_pa_cb.resolve(); - m_port[0].m_in_cb = &m_in_pa_cb; - m_out_pa_cb.resolve_safe(); - m_port[0].m_out_cb = &m_out_pa_cb; - m_in_pb_cb.resolve(); - m_port[1].m_in_cb = &m_in_pb_cb; - m_out_pb_cb.resolve_safe(); - m_port[1].m_out_cb = &m_out_pb_cb; - m_irq_cb.resolve_safe(); - - /* allocate timers */ - m_timer = timer_alloc(TIMER_END_CB); - - /* register for save states */ - save_item(NAME(m_port[0].m_in)); - save_item(NAME(m_port[0].m_out)); - save_item(NAME(m_port[0].m_ddr)); - save_item(NAME(m_port[1].m_in)); - save_item(NAME(m_port[1].m_out)); - save_item(NAME(m_port[1].m_ddr)); - - save_item(NAME(m_irqstate)); - save_item(NAME(m_irqenable)); - save_item(NAME(m_irq)); - - save_item(NAME(m_pa7dir)); - save_item(NAME(m_pa7prev)); - - save_item(NAME(m_timershift)); - save_item(NAME(m_timerstate)); -} - - - -/*------------------------------------------------- - device_reset - device-specific reset --------------------------------------------------*/ - -void riot6532_device::device_reset() -{ - /* reset I/O states */ - m_port[0].m_in = 0; - m_port[0].m_out = 0; - m_port[0].m_ddr = 0; - m_port[1].m_in = 0; - m_port[1].m_out = 0; - m_port[1].m_ddr = 0; - - /* reset IRQ states */ - m_irqenable = 0; - m_irqstate = 0; - update_irqstate(); - - /* reset PA7 states */ - m_pa7dir = 0; - m_pa7prev = 0; - - /* reset timer states */ - m_timershift = 10; - m_timerstate = TIMER_COUNTING; - m_timer->adjust(attotime::from_ticks(256 << m_timershift, clock())); -} - -void riot6532_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) -{ - switch (id) - { - case TIMER_END_CB: - timer_end(); - break; - default: - throw emu_fatalerror("Unknown id in riot6532_device::device_timer"); - } -} |