// license:BSD-3-Clause // copyright-holders:Sandro Ronco /********************************************************************** LH5810/LH5811 Input/Output Port Controller TODO: - serial data transfer - data transfer to the cassette tape **********************************************************************/ #include "emu.h" #include "lh5810.h" //************************************************************************* // MACROS / CONSTANTS //************************************************************************* enum { LH5810_RESET = 4, LH5810_U, LH5810_L, LH5820_F, LH5810_OPC, LH5810_G, LH5810_MSK, LH5810_IF, LH5810_DDA, LH5810_DDB, LH5810_OPA, LH5810_OPB }; //************************************************************************** // GLOBAL VARIABLES //************************************************************************** DEFINE_DEVICE_TYPE(LH5810, lh5810_device, "lh5810", "LH5810 I/O Port") //************************************************************************** // LIVE DEVICE //************************************************************************** //------------------------------------------------- // lh5810_device - constructor //------------------------------------------------- lh5810_device::lh5810_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : device_t(mconfig, LH5810, tag, owner, clock) , m_porta_r_cb(*this, 0) , m_porta_w_cb(*this) , m_portb_r_cb(*this, 0) , m_portb_w_cb(*this) , m_portc_w_cb(*this) , m_out_int_cb(*this) , m_irq(0) { } //------------------------------------------------- // device_start - device-specific startup //------------------------------------------------- void lh5810_device::device_start() { // register for state saving save_item(NAME(m_irq)); save_item(NAME(m_reg)); } //------------------------------------------------- // device_reset - device-specific reset //------------------------------------------------- void lh5810_device::device_reset() { memset(m_reg, 0, sizeof(m_reg)); m_irq = 0; } //------------------------------------------------- // data_r - data read //------------------------------------------------- uint8_t lh5810_device::data_r(offs_t offset) { switch (offset) { case LH5810_U: case LH5810_L: case LH5810_G: case LH5810_DDA: case LH5810_DDB: case LH5810_OPC: case LH5820_F: return m_reg[offset]; case LH5810_IF: if (BIT(m_portb_r_cb(0) & ~m_reg[LH5810_DDB], 7)) m_reg[offset] |= 2; else m_reg[offset] &= 0xfd; return m_reg[offset]; case LH5810_MSK: return (m_reg[offset]&0x0f) | (m_irq<<4) | (BIT(m_reg[LH5810_OPB],7)<<5); case LH5810_OPA: m_reg[offset] = (m_reg[offset] & m_reg[LH5810_DDA]) | (m_porta_r_cb(0) & ~m_reg[LH5810_DDA]); return m_reg[offset]; case LH5810_OPB: m_reg[offset] = (m_reg[offset] & m_reg[LH5810_DDB]) | (m_portb_r_cb(0) & ~m_reg[LH5810_DDB]); m_out_int_cb((m_reg[offset] & 0x80 && m_reg[LH5810_MSK] & 0x02) ? ASSERT_LINE : CLEAR_LINE); return m_reg[offset]; default: return 0x00; } } //------------------------------------------------- // data_w - data write //------------------------------------------------- void lh5810_device::data_w(offs_t offset, uint8_t data) { switch (offset) { case LH5810_RESET: break; case LH5810_G: case LH5820_F: case LH5810_DDA: case LH5810_DDB: m_reg[offset] = data; break; case LH5810_U: //writing on U register clear the RD flag of IF register m_reg[LH5810_IF] &= 0xfb; m_reg[offset] = data; break; case LH5810_L: //writing on L register clear the TD flag of IF register m_reg[LH5810_IF] &= 0xf7; m_reg[offset] = data; break; case LH5810_MSK: m_reg[offset] = data & 0x0f; break; case LH5810_IF: //only bit 0 and 1 are writable m_reg[offset] = (m_reg[offset] & 0xfc) | (data & 0x03); break; case LH5810_OPA: m_reg[offset] = (data & m_reg[LH5810_DDA]) | (m_reg[offset] & ~m_reg[LH5810_DDA]); m_porta_w_cb((offs_t)0, m_reg[offset]); break; case LH5810_OPB: m_reg[offset] = (data & m_reg[LH5810_DDB]) | (m_reg[offset] & ~m_reg[LH5810_DDB]); m_portb_w_cb((offs_t)0, m_reg[offset]); m_out_int_cb((m_reg[offset] & 0x80 && m_reg[LH5810_MSK] & 0x02) ? ASSERT_LINE : CLEAR_LINE); break; case LH5810_OPC: m_reg[offset] = data; m_portc_w_cb((offs_t)0, m_reg[offset]); break; } }