// license:BSD-3-Clause
// copyright-holders:Curt Coder
/**********************************************************************

    Conitec Datensysteme GRIP graphics card emulation

**********************************************************************/

#include "emu.h"
#include "grip.h"

#include "screen.h"
#include "speaker.h"



//**************************************************************************
//  MACROS / CONSTANTS
//**************************************************************************

#define SCREEN_TAG          "screen"
#define Z80_TAG             "grip_z1"
#define MC6845_TAG          "z30"
#define HD6345_TAG          "z30"
#define I8255A_TAG          "z6"
#define Z80STI_TAG          "z9"
#define CENTRONICS_TAG      "centronics"


#define VIDEORAM_SIZE       0x10000



//**************************************************************************
//  DEVICE DEFINITIONS
//**************************************************************************

DEFINE_DEVICE_TYPE(ECB_GRIP21, ecb_grip21_device, "ecb_grip21", "Conitec Datensysteme GRIP-2.1")



//**************************************************************************
//  ROMS
//**************************************************************************

//-------------------------------------------------
//  ROM( grip21 )
//-------------------------------------------------

ROM_START( grip21 )
	ROM_REGION( 0x4000, Z80_TAG, 0 )
	ROM_LOAD( "grip21.z2", 0x0000, 0x4000, CRC(7f6a37dd) SHA1(2e89f0b0c378257ff7e41c50d57d90865c6e214b) )
ROM_END


#if 0
//-------------------------------------------------
//  ROM( grip25 )
//-------------------------------------------------

ROM_START( grip25 )
	ROM_REGION( 0x4000, Z80_TAG, 0 )
	ROM_LOAD( "grip25.z2", 0x0000, 0x4000, CRC(49ebb284) SHA1(0a7eaaf89da6db2750f820146c8f480b7157c6c7) )
ROM_END


//-------------------------------------------------
//  ROM( grip26 )
//-------------------------------------------------

ROM_START( grip26 )
	ROM_REGION( 0x4000, Z80_TAG, 0 )
	ROM_LOAD( "grip26.z2", 0x0000, 0x4000, CRC(a1c424f0) SHA1(83942bc75b9475f044f936b8d9d7540551d87db9) )
ROM_END


//-------------------------------------------------
//  ROM( grip31 )
//-------------------------------------------------

ROM_START( grip31 )
	ROM_REGION( 0x4000, Z80_TAG, 0 )
	ROM_LOAD( "grip31.z2", 0x0000, 0x4000, CRC(e0e4e8ab) SHA1(73d3d14c9b06fed0c187fb0fffe5ec035d8dd256) )
ROM_END


//-------------------------------------------------
//  ROM( grip562 )
//-------------------------------------------------

ROM_START( grip562 )
	ROM_REGION( 0x8000, Z80_TAG, 0 )
	ROM_LOAD( "grip562.z2", 0x0000, 0x8000, CRC(74be0455) SHA1(1c423ecca6363345a8690ddc45dbafdf277490d3) )
ROM_END


//-------------------------------------------------
//  ROM( grips115 )
//-------------------------------------------------

ROM_START( grips115 )
	ROM_REGION( 0x4000, Z80_TAG, 0 )
	ROM_LOAD( "grips115.z2", 0x0000, 0x4000, CRC(505706ef) SHA1(05fb032fb1a504c534c30c352ba4bd47623503d0) )
ROM_END
#endif


//-------------------------------------------------
//  rom_region - device-specific ROM region
//-------------------------------------------------

const tiny_rom_entry *ecb_grip21_device::device_rom_region() const
{
	return ROM_NAME( grip21 );
}



//**************************************************************************
//  ADDRESS MAPS
//**************************************************************************

//-------------------------------------------------
//  ADDRESS_MAP( grip_mem )
//-------------------------------------------------

void ecb_grip21_device::grip_mem(address_map &map)
{
	map(0x0000, 0x3fff).rom();
	map(0x4000, 0x47ff).ram();
	map(0x8000, 0xffff).bankrw("videoram");
}


//-------------------------------------------------
//  ADDRESS_MAP( grip_io )
//-------------------------------------------------

void ecb_grip21_device::grip_io(address_map &map)
{
	map.global_mask(0xff);
	map(0x00, 0x00).rw(FUNC(ecb_grip21_device::cxstb_r), FUNC(ecb_grip21_device::cxstb_w));
//  map(0x10, 0x10).w(FUNC(ecb_grip21_device::ccon_w));
	map(0x11, 0x11).w(FUNC(ecb_grip21_device::vol0_w));
//  map(0x12, 0x12).w(FUNC(ecb_grip21_device::rts_w));
	map(0x13, 0x13).w(FUNC(ecb_grip21_device::page_w));
//  map(0x14, 0x14).w(FUNC(ecb_grip21_device::cc1_w));
//  map(0x15, 0x15).w(FUNC(ecb_grip21_device::cc2_w));
	map(0x16, 0x16).w(FUNC(ecb_grip21_device::flash_w));
	map(0x17, 0x17).w(FUNC(ecb_grip21_device::vol1_w));
	map(0x20, 0x2f).rw(m_sti, FUNC(z80sti_device::read), FUNC(z80sti_device::write));
	map(0x30, 0x30).rw(FUNC(ecb_grip21_device::lrs_r), FUNC(ecb_grip21_device::lrs_w));
	map(0x40, 0x40).r(FUNC(ecb_grip21_device::stat_r));
	map(0x50, 0x50).w(MC6845_TAG, FUNC(mc6845_device::address_w));
	map(0x52, 0x52).w(MC6845_TAG, FUNC(mc6845_device::register_w));
	map(0x53, 0x53).r(MC6845_TAG, FUNC(mc6845_device::register_r));
	map(0x60, 0x60).w("cent_data_out", FUNC(output_latch_device::write));
	map(0x70, 0x73).rw(I8255A_TAG, FUNC(i8255_device::read), FUNC(i8255_device::write));
//  map(0x80, 0x80).w(FUNC(ecb_grip21_device::bl2out_w));
//  map(0x90, 0x90).w(FUNC(ecb_grip21_device::gr2out_w));
//  map(0xa0, 0xa0).w(FUNC(ecb_grip21_device::rd2out_w));
//  map(0xb0, 0xb0).w(FUNC(ecb_grip21_device::clrg2_w));
//  map(0xc0, 0xc0).w(FUNC(ecb_grip21_device::bluout_w));
//  map(0xd0, 0xd0).w(FUNC(ecb_grip21_device::grnout_w));
//  map(0xe0, 0xe0).w(FUNC(ecb_grip21_device::redout_w));
//  map(0xf0, 0xf0).w(FUNC(ecb_grip21_device::clrg1_w));
}


//**************************************************************************
//  DEVICE CONFIGURATION
//**************************************************************************

//-------------------------------------------------
//  mc6845
//-------------------------------------------------

MC6845_UPDATE_ROW( ecb_grip21_device::crtc_update_row )
{
	for (int column = 0; column < x_count; column++)
	{
		uint16_t const address = (m_page << 12) | (((ma + column) & 0xfff) << 3) | (ra & 0x07);
		uint8_t const data = m_video_ram[address];

		for (int bit = 0; bit < 8; bit++)
		{
			int const x = (column * 8) + bit;
			int const color = (m_flash ? 0 : BIT(data, bit)) && de;

			bitmap.pix(vbp + y, hbp + x) = m_palette->pen(color);
		}
	}
}
/*
MC6845_UPDATE_ROW( ecb_grip21_device::grip5_update_row )
{
    rgb_t const *const palette = m_palette->palette()->entry_list_raw();
    for (int column = 0; column < x_count; column++)
    {
        uint16_t const address = (m_dpage << 12) | (((ma + column) & 0xfff) << 3) | (ra & 0x07);
        uint8_t const data = m_video_ram[address];

        for (int bit = 0; bit < 8; bit++)
        {
            int const x = (column * 8) + bit;
            int const color = m_flash ? 0 : BIT(data, bit);

            bitmap.pix(y, x) = palette[color];
        }
    }
}

MC6845_ON_UPDATE_ADDR_CHANGED( ecb_grip21_device::grip5_addr_changed )
{
}
*/

static const double speaker_levels[] = { -1.0, 0.0, 1.0, 0.0 };

//-------------------------------------------------
//  I8255A interface
//-------------------------------------------------

uint8_t ecb_grip21_device::ppi_pa_r()
{
	/*

	    bit     description

	    PA0     ECB bus D0
	    PA1     ECB bus D1
	    PA2     ECB bus D2
	    PA3     ECB bus D3
	    PA4     ECB bus D4
	    PA5     ECB bus D5
	    PA6     ECB bus D6
	    PA7     ECB bus D7

	*/

	return m_ppi_pa;
}

void ecb_grip21_device::ppi_pa_w(uint8_t data)
{
	/*

	    bit     description

	    PA0     ECB bus D0
	    PA1     ECB bus D1
	    PA2     ECB bus D2
	    PA3     ECB bus D3
	    PA4     ECB bus D4
	    PA5     ECB bus D5
	    PA6     ECB bus D6
	    PA7     ECB bus D7

	*/

	m_ppi_pa = data;
}

uint8_t ecb_grip21_device::ppi_pb_r()
{
	/*

	    bit     description

	    PB0     Keyboard input
	    PB1     Keyboard input
	    PB2     Keyboard input
	    PB3     Keyboard input
	    PB4     Keyboard input
	    PB5     Keyboard input
	    PB6     Keyboard input
	    PB7     Keyboard input

	*/

	return m_keydata;
}

void ecb_grip21_device::ppi_pc_w(uint8_t data)
{
	/*

	    bit     signal      description

	    PC0     INTRB       interrupt B output (keyboard)
	    PC1     KBF         input buffer B full output (keyboard)
	    PC2     _KBSTB      strobe B input (keyboard)
	    PC3     INTRA       interrupt A output (PROF-80)
	    PC4     _STBA       strobe A input (PROF-80)
	    PC5     IBFA        input buffer A full output (PROF-80)
	    PC6     _ACKA       acknowledge A input (PROF-80)
	    PC7     _OBFA       output buffer full output (PROF-80)

	*/

	// keyboard interrupt
	m_ib = BIT(data, 0);
	m_sti->i4_w(m_ib);

	// keyboard buffer full
	m_kbf = BIT(data, 1);

	// PROF-80 interrupt
	m_ia = BIT(data, 3);
	m_sti->i7_w(m_ia);

	// PROF-80 handshaking
	m_ppi_pc = (!BIT(data, 7) << 7) | (!BIT(data, 5) << 6) | (m_ppi->pa_r() & 0x3f);
}

//-------------------------------------------------
//  Z80STI_INTERFACE( sti_intf )
//-------------------------------------------------

WRITE_LINE_MEMBER(ecb_grip21_device::write_centronics_busy)
{
	m_centronics_busy = state;
}

uint8_t ecb_grip21_device::sti_gpio_r()
{
	/*

	    bit     signal      description

	    I0      _CTS        RS-232 clear to send input
	    I1      DE          MC6845 display enable input
	    I2      CURSOR      MC6845 cursor input
	    I3      BUSY        Centronics busy input
	    I4      IB          PPI8255 PC0 input
	    I5      _SKBD       Serial keyboard input
	    I6      EXIN        External interrupt input
	    I7      IA          PPI8255 PC3 input

	*/

	uint8_t data = 0x20;

	// display enable
	data |= m_crtc->de_r() << 1;

	// cursor
	data |= m_crtc->cursor_r() << 2;

	// centronics busy
	data |= m_centronics_busy << 3;

	// keyboard interrupt
	data |= m_ib << 4;

	// PROF-80 interrupt
	data |= m_ia << 7;

	return data;
}

WRITE_LINE_MEMBER( ecb_grip21_device::speaker_w )
{
	int level = state && ((m_vol1 << 1) | m_vol0);

	m_speaker->level_w(level);
}

//-------------------------------------------------
//  z80_daisy_config grip_daisy_chain
//-------------------------------------------------

static const z80_daisy_config grip_daisy_chain[] =
{
	{ Z80STI_TAG },
	{ nullptr }
};


//-------------------------------------------------
//  ASCII_KEYBOARD_INTERFACE( kb_intf )
//-------------------------------------------------

void ecb_grip21_device::kb_w(uint8_t data)
{
	if (!m_kbf)
	{
		m_keydata = data;

		// trigger GRIP 8255 port C bit 2 (_STBB)
		m_ppi->pc2_w(0);
		m_ppi->pc2_w(1);
	}
}

//**************************************************************************
//  MACHINE CONFIGURATION
//**************************************************************************


//-------------------------------------------------
//  device_add_mconfig - add device configuration
//-------------------------------------------------


void ecb_grip21_device::device_add_mconfig(machine_config &config)
{
	// basic machine hardware
	z80_device& z80(Z80(config, Z80_TAG, XTAL(16'000'000)/4));
	z80.set_daisy_config(grip_daisy_chain);
	z80.set_addrmap(AS_PROGRAM, &ecb_grip21_device::grip_mem);
	z80.set_addrmap(AS_IO, &ecb_grip21_device::grip_io);

	// video hardware
	screen_device &screen(SCREEN(config, SCREEN_TAG, SCREEN_TYPE_RASTER));
	screen.set_color(rgb_t::white());
	screen.set_refresh_hz(50);
	screen.set_vblank_time(ATTOSECONDS_IN_USEC(2500)); // not accurate
	screen.set_screen_update(MC6845_TAG, FUNC(mc6845_device::screen_update));
	screen.set_size(640, 480);
	screen.set_visarea(0, 640-1, 0, 480-1);

	PALETTE(config, m_palette, palette_device::MONOCHROME);

	// sound hardware
	SPEAKER(config, "mono").front_center();
	SPEAKER_SOUND(config, m_speaker);
	m_speaker->set_levels(4, speaker_levels);
	m_speaker->add_route(ALL_OUTPUTS, "mono", 0.25);

	// devices
	MC6845(config, m_crtc, XTAL(16'000'000)/4);
	m_crtc->set_screen(SCREEN_TAG);
	m_crtc->set_show_border_area(true);
	m_crtc->set_char_width(8);
	m_crtc->set_update_row_callback(FUNC(ecb_grip21_device::crtc_update_row));
	m_crtc->out_de_callback().set(m_sti, FUNC(z80sti_device::i1_w));
	m_crtc->out_cur_callback().set(m_sti, FUNC(z80sti_device::i1_w));

//  HD6345(config, HD6345_TAG, XTAL(16'000'000)/4).set_screen(SCREEN_TAG);

	I8255A(config, m_ppi);
	m_ppi->in_pa_callback().set(FUNC(ecb_grip21_device::ppi_pa_r));
	m_ppi->out_pa_callback().set(FUNC(ecb_grip21_device::ppi_pa_w));
	m_ppi->in_pb_callback().set(FUNC(ecb_grip21_device::ppi_pb_r));
	m_ppi->out_pc_callback().set(FUNC(ecb_grip21_device::ppi_pc_w));

	Z80STI(config, m_sti, XTAL(16'000'000)/4);
	m_sti->out_int_cb().set_inputline(Z80_TAG, INPUT_LINE_IRQ0);
	m_sti->in_gpio_cb().set(FUNC(ecb_grip21_device::sti_gpio_r));
	m_sti->out_tbo_cb().set(FUNC(ecb_grip21_device::speaker_w));
	m_sti->out_tco_cb().set(m_sti, FUNC(z80sti_device::tc_w));
	m_sti->out_tdo_cb().set(m_sti, FUNC(z80sti_device::tc_w));

	CENTRONICS(config, m_centronics, centronics_devices, "printer");
	m_centronics->busy_handler().set(FUNC(ecb_grip21_device::write_centronics_busy));
	m_centronics->fault_handler().set(FUNC(ecb_grip21_device::write_centronics_fault));

	output_latch_device &cent_data_out(OUTPUT_LATCH(config, "cent_data_out"));
	m_centronics->set_output_latch(cent_data_out);

	generic_keyboard_device &keyboard(GENERIC_KEYBOARD(config, "keyboard", 0));
	keyboard.set_keyboard_callback(FUNC(ecb_grip21_device::kb_w));
}


//**************************************************************************
//  INPUT PORTS
//**************************************************************************

//-------------------------------------------------
//  INPUT_PORTS( grip )
//-------------------------------------------------

static INPUT_PORTS_START( grip )
	PORT_START("J1")
	PORT_CONFNAME( 0x01, 0x00, "J1 EPROM Type")
	PORT_CONFSETTING( 0x00, "2732" )
	PORT_CONFSETTING( 0x01, "2764/27128" )

	PORT_START("J2")
	PORT_CONFNAME( 0x03, 0x00, "J2 Centronics Mode")
	PORT_CONFSETTING( 0x00, "Mode 1" )
	PORT_CONFSETTING( 0x01, "Mode 2" )
	PORT_CONFSETTING( 0x02, "Mode 3" )

	PORT_START("J3A")
	PORT_CONFNAME( 0x07, 0x00, "J3 Host")
	PORT_CONFSETTING( 0x00, "ECB Bus" )
	PORT_CONFSETTING( 0x01, "V24 9600 Baud" )
	PORT_CONFSETTING( 0x02, "V24 4800 Baud" )
	PORT_CONFSETTING( 0x03, "V24 1200 Baud" )
	PORT_CONFSETTING( 0x04, "Keyboard" )

	PORT_START("J3B")
	PORT_CONFNAME( 0x07, 0x00, "J3 Keyboard")
	PORT_CONFSETTING( 0x00, "Parallel" )
	PORT_CONFSETTING( 0x01, "Serial (1200 Baud, 8 Bits)" )
	PORT_CONFSETTING( 0x02, "Serial (1200 Baud, 7 Bits)" )
	PORT_CONFSETTING( 0x03, "Serial (600 Baud, 8 Bits)" )
	PORT_CONFSETTING( 0x04, "Serial (600 Baud, 7 Bits)" )

	PORT_START("J4")
	PORT_CONFNAME( 0x01, 0x00, "J4 COLOR")
	PORT_CONFSETTING( 0x00, DEF_STR( No ) )
	PORT_CONFSETTING( 0x01, DEF_STR( Yes ) )

	PORT_START("J5")
	PORT_CONFNAME( 0x01, 0x01, "J5 Power On Reset")
	PORT_CONFSETTING( 0x00, "External" )
	PORT_CONFSETTING( 0x01, "Internal" )

	PORT_START("J6")
	PORT_CONFNAME( 0x03, 0x00, "J6 Serial Clock")
	PORT_CONFSETTING( 0x00, "TC/16, TD/16, TD" )
	PORT_CONFSETTING( 0x01, "TD/16, TD/16, TD" )
	PORT_CONFSETTING( 0x02, "TC/16, BAUD/16, input" )
	PORT_CONFSETTING( 0x03, "BAUD/16, BAUD/16, input" )

	PORT_START("J7")
	PORT_CONFNAME( 0xff, 0xc0, "J7 ECB Bus Address")
	PORT_CONFSETTING( 0xc0, "C0/C1" )
	PORT_CONFSETTING( 0xa0, "A0/A1" )

	PORT_START("J8")
	PORT_CONFNAME( 0x01, 0x00, "J8 Video RAM")
	PORT_CONFSETTING( 0x00, "32 KB" )
	PORT_CONFSETTING( 0x01, "64 KB" )

	PORT_START("J9")
	PORT_CONFNAME( 0x01, 0x01, "J9 CPU Clock")
	PORT_CONFSETTING( 0x00, "2 MHz" )
	PORT_CONFSETTING( 0x01, "4 MHz" )

	PORT_START("J10")
	PORT_CONFNAME( 0x01, 0x01, "J10 Pixel Clock")
	PORT_CONFSETTING( 0x00, "External" )
	PORT_CONFSETTING( 0x01, "Internal" )
INPUT_PORTS_END


//-------------------------------------------------
//  input_ports - device-specific input ports
//-------------------------------------------------

ioport_constructor ecb_grip21_device::device_input_ports() const
{
	return INPUT_PORTS_NAME( grip );
}



//**************************************************************************
//  LIVE DEVICE
//**************************************************************************

//-------------------------------------------------
//  ecb_grip21_device - constructor
//-------------------------------------------------

ecb_grip21_device::ecb_grip21_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
	device_t(mconfig, ECB_GRIP21, tag, owner, clock),
	device_ecbbus_card_interface(mconfig, *this),
	m_ppi(*this, I8255A_TAG),
	m_sti(*this, Z80STI_TAG),
	m_crtc(*this, MC6845_TAG),
	m_centronics(*this, CENTRONICS_TAG),
	m_palette(*this, "palette"),
	m_speaker(*this, "speaker"),
	m_video_ram(*this, "video_ram", VIDEORAM_SIZE, ENDIANNESS_LITTLE),
	m_j3a(*this, "J3A"),
	m_j3b(*this, "J3B"),
	m_j7(*this, "J7"),
	m_centronics_busy(0),
	m_centronics_fault(0),
	m_vol0(0),
	m_vol1(0),
	m_ia(0),
	m_ib(0),
	m_keydata(0),
	m_kbf(0),
	m_lps(0),
	m_page(0),
	m_flash(0),
	m_base(0),
	m_ppi_pa(0),
	m_ppi_pc(0)
{
}

//-------------------------------------------------
//  device_start - device-specific startup
//-------------------------------------------------

void ecb_grip21_device::device_start()
{
	// setup GRIP memory banking
	membank("videoram")->configure_entries(0, 2, m_video_ram, 0x8000);
	membank("videoram")->set_entry(0);

	// register for state saving
	save_item(NAME(m_vol0));
	save_item(NAME(m_vol1));
	save_item(NAME(m_keydata));
	save_item(NAME(m_kbf));
	save_item(NAME(m_lps));
	save_item(NAME(m_page));
	save_item(NAME(m_flash));
}

/*
void grip5_state::machine_start()
{
    ecb_grip21_device::machine_start();

    // setup ROM banking
    membank("eprom")->configure_entries(0, 2, memregion(Z80_TAG)->base(), 0x4000);
    *this.root_device().membank("eprom")->set_entry(0);

    // register for state saving
    save_item(NAME(m_dpage));
}
*/

//-------------------------------------------------
//  device_reset - device-specific reset
//-------------------------------------------------

void ecb_grip21_device::device_reset()
{
	m_base = m_j7->read();
	m_page = 0;
	m_lps = 0;
}


//-------------------------------------------------
//  vol0_w - volume 0
//-------------------------------------------------

void ecb_grip21_device::vol0_w(uint8_t data)
{
	m_vol0 = BIT(data, 7);
}


//-------------------------------------------------
//  vol1_w - volume 1
//-------------------------------------------------

void ecb_grip21_device::vol1_w(uint8_t data)
{
	m_vol1 = BIT(data, 7);
}


//-------------------------------------------------
//  flash_w -
//-------------------------------------------------

void ecb_grip21_device::flash_w(uint8_t data)
{
	m_flash = BIT(data, 7);
}


//-------------------------------------------------
//  page_w - video page select
//-------------------------------------------------

void ecb_grip21_device::page_w(uint8_t data)
{
	m_page = BIT(data, 7);

	membank("videoram")->set_entry(m_page);
}


//-------------------------------------------------
//  stat_r -
//-------------------------------------------------

WRITE_LINE_MEMBER(ecb_grip21_device::write_centronics_fault)
{
	m_centronics_fault = state;
}

uint8_t ecb_grip21_device::stat_r()
{
	/*

	    bit     signal      description

	    0       LPA0
	    1       LPA1
	    2       LPA2
	    3       SENSE
	    4       JS0
	    5       JS1
	    6       _ERROR
	    7       LPSTB       light pen strobe

	*/

	uint8_t data = 0;
	int js0 = 0, js1 = 0;

	// JS0
	switch (m_j3a->read())
	{
	case 0: js0 = 0; break;
	case 1: js0 = 1; break;
	case 2: js0 = m_vol0; break;
	case 3: js0 = m_vol1; break;
	case 4: js0 = m_page; break;
	}

	data |= js0 << 4;

	// JS1
	switch (m_j3b->read())
	{
	case 0: js1 = 0; break;
	case 1: js1 = 1; break;
	case 2: js1 = m_vol0; break;
	case 3: js1 = m_vol1; break;
	case 4: js1 = m_page; break;
	}

	data |= js1 << 5;

	// centronics fault
	data |= m_centronics_fault << 6;

	// light pen strobe
	data |= m_lps << 7;

	return data;
}


//-------------------------------------------------
//  lrs_r -
//-------------------------------------------------

uint8_t ecb_grip21_device::lrs_r()
{
	if (!machine().side_effects_disabled())
		m_lps = 0;

	return 0;
}


//-------------------------------------------------
//  lrs_w -
//-------------------------------------------------

void ecb_grip21_device::lrs_w(uint8_t data)
{
	m_lps = 0;
}


//-------------------------------------------------
//  cxstb_r - centronics strobe
//-------------------------------------------------

uint8_t ecb_grip21_device::cxstb_r()
{
	if (!machine().side_effects_disabled())
	{
		m_centronics->write_strobe(0);
		m_centronics->write_strobe(1);
	}

	return 0;
}


//-------------------------------------------------
//  cxstb_w - centronics strobe
//-------------------------------------------------

void ecb_grip21_device::cxstb_w(uint8_t data)
{
	m_centronics->write_strobe(0);
	m_centronics->write_strobe(1);
}

/*
//-------------------------------------------------
//  eprom_w - EPROM bank select
//-------------------------------------------------

void grip5_state::eprom_w(uint8_t data)
{
    membank("eprom")->set_entry(BIT(data, 0));
}


//-------------------------------------------------
//  dpage_w - display page select
//-------------------------------------------------

void grip5_state::dpage_w(uint8_t data)
{
    m_dpage = BIT(data, 7);
}
*/


//-------------------------------------------------
//  ecbbus_io_r - I/O read
//-------------------------------------------------

uint8_t ecb_grip21_device::ecbbus_io_r(offs_t offset)
{
	uint8_t data = 0;

	if ((offset & 0xfe) == m_base)
	{
		if (BIT(offset, 0))
		{
			data = m_ppi_pa;

			// acknowledge PPI port A
			m_ppi->pc6_w(0);
			m_ppi->pc6_w(1);
		}
		else
		{
			data = m_ppi_pc;
		}
	}

	return data;
}


//-------------------------------------------------
//  ecbbus_io_w - I/O write
//-------------------------------------------------

void ecb_grip21_device::ecbbus_io_w(offs_t offset, uint8_t data)
{
	if ((offset & 0xfe) == m_base)
	{
		if (BIT(offset, 0))
		{
			m_ppi_pa = data;

			// strobe PPI port A
			m_ppi->pc4_w(0);
			m_ppi->pc4_w(1);
		}
	}
}
