diff --git a/src/mame/adp/servicetastatur.cpp b/src/mame/adp/servicetastatur.cpp index dcefb92561e8b..d5ab00f4f97ae 100644 --- a/src/mame/adp/servicetastatur.cpp +++ b/src/mame/adp/servicetastatur.cpp @@ -40,12 +40,17 @@ ___| XTAL 80C31 +KEYPAD+ |__ */ #include "emu.h" + +#include "bus/rs232/rs232.h" #include "cpu/mcs51/i80c51.h" #include "machine/i2cmem.h" #include "video/hd44780.h" + #include "emupal.h" #include "screen.h" +#include "servicet.lh" + namespace { enum @@ -80,11 +85,15 @@ class servicet_state : public driver_device m_maincpu(*this, "maincpu"), m_i2cmem(*this, "eeprom"), m_lcd(*this, "hd44780"), + m_dte(*this, "dte"), m_io_keys(*this, "IN%u", 0U) + { } void servicet(machine_config &config) ATTR_COLD; + DECLARE_INPUT_CHANGED_MEMBER(en_w); + protected: virtual void machine_start() override ATTR_COLD; virtual void machine_reset() override ATTR_COLD; @@ -92,24 +101,40 @@ class servicet_state : public driver_device private: uint8_t port1_r(); void port1_w(uint8_t data); + uint8_t port3_r(); void port3_w(uint8_t data); - uint8_t bus_r(offs_t offset); - void bus_w(offs_t offset, uint8_t data); + + uint8_t gsg_scramble(uint8_t data); + + uint8_t gsg_r(offs_t offset); + void gsg_w(offs_t offset, uint8_t data); + + void enable_in(int state); + void clock_in(int state); + void data_in(int state); void servicet_data(address_map &map) ATTR_COLD; void servicet_map(address_map &map) ATTR_COLD; + void palette_init(palette_device &palette); + HD44780_PIXEL_UPDATE(servicet_pixel_update); required_device m_maincpu; required_device m_i2cmem; required_device m_lcd; + required_device m_dte; required_ioport_array<3> m_io_keys; + bool m_datain = 0; + uint8_t m_port1 = 0xff; uint8_t m_port3 = 0xff; - uint8_t m_lcd_data = 0; + + uint8_t m_u13 = 0xff; + uint8_t m_u19 = 0xff; + uint8_t m_u20 = 0xff; }; void servicet_state::servicet_map(address_map &map) @@ -119,90 +144,104 @@ void servicet_state::servicet_map(address_map &map) void servicet_state::servicet_data(address_map &map) { - map(0x0000, 0xffff).rw(FUNC(servicet_state::bus_r), FUNC(servicet_state::bus_w)); + map(0x0070, 0x0070).w(m_lcd, FUNC(hd44780_device::control_w)); + map(0x0071, 0x0071).r(m_lcd, FUNC(hd44780_device::control_r)); + map(0x0072, 0x0072).w(m_lcd, FUNC(hd44780_device::data_w)); + map(0x0073, 0x0073).r(m_lcd, FUNC(hd44780_device::data_r)); + + map(0x0010, 0x0030).w(FUNC(servicet_state::gsg_w)); + map(0x0040, 0x0050).r(FUNC(servicet_state::gsg_r)); + map(0x0060, 0x0060).w(FUNC(servicet_state::gsg_w)); + map(0x4000, 0x4000).w(FUNC(servicet_state::gsg_w)); } static INPUT_PORTS_START( servicet ) PORT_START("IN0") // P1.0 - PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("OK") PORT_CODE(KEYCODE_ENTER) - PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("F4") PORT_CODE(KEYCODE_F4) - PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP) PORT_4WAY + PORT_BIT( 0x0f, IP_ACTIVE_LOW, IPT_UNUSED) + PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_START) PORT_NAME("OK") + PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON4) PORT_NAME("F4") + PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_UP) PORT_4WAY + PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED) PORT_START("IN1") // P1.1 - PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT) PORT_4WAY - PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT) PORT_4WAY - PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN) PORT_4WAY + PORT_BIT( 0x0f, IP_ACTIVE_LOW, IPT_UNUSED) + PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT) PORT_4WAY + PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT) PORT_4WAY + PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN) PORT_4WAY + PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED) PORT_START("IN2") // P1.2 - PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("F3") PORT_CODE(KEYCODE_F3) - PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("F1") PORT_CODE(KEYCODE_F1) - PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("F2") PORT_CODE(KEYCODE_F2) + PORT_BIT( 0x0f, IP_ACTIVE_LOW, IPT_UNUSED) + PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON3) PORT_NAME("F3") + PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_NAME("F1") + PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON2) PORT_NAME("F2") + PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED) + + PORT_START("P3") // P3 + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNUSED) + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNUSED) + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_SERVICE1) PORT_NAME("INT0") PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(servicet_state::en_w), 0) //MCS51_INT0_LINE + PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_SERVICE1) PORT_NAME("INT1") PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(servicet_state::en_w), 0) //MCS51_INT1_LINE + PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_CUSTOM) PORT_READ_LINE_DEVICE_MEMBER("eeprom", FUNC(i2cmem_device::read_sda)) + PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNUSED) + PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED) + PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED) INPUT_PORTS_END void servicet_state::machine_start() { save_item(NAME(m_port1)); save_item(NAME(m_port3)); - save_item(NAME(m_lcd_data)); + + save_item(NAME(m_u13)); + save_item(NAME(m_u19)); + save_item(NAME(m_u20)); } void servicet_state::machine_reset() { m_port1 = 0xff; m_port3 = 0xff; - m_lcd_data = 0; + + m_u13 = 0xff; + m_u19 = 0xff; + m_u20 = 0xff; } uint8_t servicet_state::port1_r() { - uint8_t data = m_port1; // Start with what was written to port1 + /* + * the keypad scan works by writing 0xfb,0xfd,0xfe (pulling rows low) to port 1 + * send seeing which bits end up low instead of high + */ + uint8_t data = m_port1; - // key matrix scanning seems to be bidirectional - // CPU drives each line HIGH and checks if connected lines are also HIGH = button pressed - - // Column-to-Row scanning: When columns (P1.0-P1.2) are driven HIGH - for (int col = 0; col < 3; col++) - { - if (BIT(m_port1, col)) // Column is driven HIGH - { - uint8_t const keys = m_io_keys[col]->read(); - data |= (keys & 0x70); // Mask to only row bits (4,5,6) - } - } - - // Row-to-Column scanning: When rows (P1.4-P1.6) are driven HIGH - for (int row = 0; row < 3; row++) - { - if (BIT(m_port1, row + 4)) // Row is driven HIGH (bits 4,5,6) - { - // Check all columns for this row - for (int col = 0; col < 3; col++) - { - uint8_t const keys = m_io_keys[col]->read(); - if (BIT(keys, row + 4)) // Key pressed in this row - { - data |= (1 << col); // Set corresponding column bit HIGH - } - } - } - } + if (BIT(m_port1, 0)==0) data &= m_io_keys[0]->read(); + if (BIT(m_port1, 1)==0) data &= m_io_keys[1]->read(); + if (BIT(m_port1, 2)==0) data &= m_io_keys[2]->read(); return data; } + void servicet_state::port1_w(uint8_t data) { m_port1 = data; } +INPUT_CHANGED_MEMBER(servicet_state::en_w) +{ + enable_in(newval); +} + uint8_t servicet_state::port3_r() { - uint8_t data = m_port3; + uint8_t data = m_io_keys[3]->read(); - uint8_t const sda = m_i2cmem->read_sda(); + uint8_t const SDA = m_i2cmem->read_sda(); // Clear bit 4 (SDA) and insert actual value from EEPROM - data = (data & ~(1 << PORT_3_SDA)) | (sda ? (1 << PORT_3_SDA) : 0); + data = (data & ~(1 << PORT_3_SDA)) | (SDA ? (1 << PORT_3_SDA) : 0); return data; } @@ -215,70 +254,115 @@ void servicet_state::port3_w(uint8_t data) m_i2cmem->write_scl(BIT(data, PORT_3_SCL)); } -uint8_t servicet_state::bus_r(offs_t offset) +uint8_t servicet_state::gsg_scramble(uint8_t data) +{ + bool d1 = BIT(data,1); + bool d2 = BIT(data,2); + bool d3 = BIT(data,3); + + // zero d1-d3 + data &= ~(0b1110); + + // d1 and d3 are swapped + data |= (d3 << 1) | (d2 << 2) | (d1 << 3); + + return data; +} + +uint8_t servicet_state::gsg_r(offs_t offset) { uint8_t data = 0xff; - // LCD is mapped to addresses where A6:A4 = 111 (0x70-0x7f) - if ((offset & 0x70) == 0x70) + switch (offset & 0x70) { - // RS and RW are A1 and A0 - bool rs = BIT(offset, 1); - bool rw = BIT(offset, 0); - - if (rw) - { - m_lcd->rs_w(rs); - m_lcd->rw_w(1); - - m_lcd->e_w(1); - data = m_lcd->db_r(); - m_lcd->e_w(0); - } - else - { - data = m_lcd_data; - } + case 0x40: //Y4 U20 OE + { + popmessage("Read GSG"); + data = m_u20; + break; } - else + case 0x50: //Y5 U19 OE { - //LOG("Bus read: %02X to %04X\n", offset); + popmessage("Read scrambled GSG"); + data = gsg_scramble(m_u19); + break; + } + case 0x60: //Y6 U13 PL + { + popmessage("Read GSG out"); + data = m_u13; + break; + } + default: + popmessage("Read unknown %02X", offset); } - return data; } -void servicet_state::bus_w(offs_t offset, uint8_t data) +void servicet_state::gsg_w(offs_t offset, uint8_t data) { - // LCD is mapped to addresses where A6:A4 = 111 (0x70-0x7f) - if ((offset & 0x70) == 0x70) + switch (offset & 0x70) { - // RS and RW are A1 and A0 - bool const rs = BIT(offset, 1); - bool const rw = BIT(offset, 0); - - if (!rw) - { - m_lcd_data = data; - - m_lcd->rs_w(rs); - m_lcd->rw_w(0); - m_lcd->db_w(data); - - m_lcd->e_w(1); - m_lcd->e_w(0); - } + case 0x40: //Y4 U20 OE + { + m_u20 = data; + popmessage("Wrote U20: %02X", data); + break; } - else if (offset == 0x4000) + case 0x50: //Y5 U19 OE { - //LOG("GSG write: %02X \n", data, offset); + m_u13 = gsg_scramble(data); + popmessage("Wrote U13: %02X", data); + break; } - else + case 0x60: //Y6 U13 PL { - //LOG("Bus write: %02X to %04X\n", data, offset); + m_u13 = data; + popmessage("Send to machine: %02X", data); + break; + } + default: + { + popmessage("Unknown write: %02X to %04X\n", data, offset); + } } } +void servicet_state::data_in(int state) +{ + m_datain = state; +} + +void servicet_state::clock_in(int state) +{ + if (state) + { + // --- INPUT SHIFT CHAIN (U20 + U19, 74HC4094) --- + uint16_t chain = (m_u19 << 8) | m_u20; + chain = ((chain << 1) | m_datain) & 0xffff; + m_u20 = chain & 0xff; + m_u19 = (chain >> 8) & 0xff; + + // --- OUTPUT SHIFT REGISTER (U13, 74HC165) --- + int q7 = (m_u13 >> 7) & 1; + m_dte->write_txd(q7); + m_u13 = (m_u13 << 1) & 0xff; + } +} + +void servicet_state::enable_in(int newval) +{ + //strobe u19 and u20 + m_maincpu->set_input_line(MCS51_INT1_LINE, newval ? ASSERT_LINE : CLEAR_LINE); + m_maincpu->set_input_line(MCS51_INT0_LINE, newval ? CLEAR_LINE : ASSERT_LINE); +} + +void servicet_state::palette_init(palette_device &palette) +{ + palette.set_pen_color(0, rgb_t(65, 165, 115)); + palette.set_pen_color(1, rgb_t(0, 50, 25)); +} + void servicet_state::servicet(machine_config &config) { I80C31(config, m_maincpu, 11.0592_MHz_XTAL); @@ -293,6 +377,12 @@ void servicet_state::servicet(machine_config &config) // I2C EEPROM: 24C16 (2KB) - connected to P3.4 (SDA) and P3.5 (SCL) I2C_24C16(config, m_i2cmem); + // SERIAL: WE ARE THE DCE + RS232_PORT(config, m_dte, default_rs232_devices, nullptr); + m_dte->dsr_handler().set(FUNC(servicet_state::enable_in)); + m_dte->rxd_handler().set(FUNC(servicet_state::data_in)); + m_dte->cts_handler().set(FUNC(servicet_state::clock_in)); + // LCD4002A screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_LCD)); screen.set_color(rgb_t(6, 120, 245)); @@ -303,7 +393,7 @@ void servicet_state::servicet(machine_config &config) screen.set_screen_update("hd44780", FUNC(hd44780_device::screen_update)); screen.set_palette("palette"); - PALETTE(config, "palette", palette_device::MONOCHROME_INVERTED); + PALETTE(config, "palette", FUNC(servicet_state::palette_init), 2); HD44780(config, m_lcd, 270'000); m_lcd->set_lcd_size(2, 40); // 2 lines, 40 characters @@ -318,4 +408,4 @@ ROM_END } // anonymous namespace -GAME( 1992, servicet, 0, servicet, servicet, servicet_state, empty_init, ROT0, "ADP", u8"Merkur Service Testgerät", MACHINE_NOT_WORKING | MACHINE_NO_SOUND_HW ) +GAMEL( 1992, servicet, 0, servicet, servicet, servicet_state, empty_init, ROT0, "ADP", u8"Merkur Service Testgerät", MACHINE_NOT_WORKING | MACHINE_NO_SOUND_HW, layout_servicet ) diff --git a/src/mame/adp/stellafr.cpp b/src/mame/adp/stellafr.cpp index 5a96275ce225b..ef16f2fbc973c 100644 --- a/src/mame/adp/stellafr.cpp +++ b/src/mame/adp/stellafr.cpp @@ -90,18 +90,21 @@ Sound and I/O board: #include "emu.h" + +#include "bus/rs232/rs232.h" #include "cpu/m68000/m68000.h" #include "machine/mc68681.h" #include "machine/nvram.h" #include "sound/ay8910.h" #include "sound/dac.h" + #include "speaker.h" +#include "stellafr.lh" + //#define VERBOSE 1 #include "logmacro.h" -#include "stellafr.lh" - namespace { enum @@ -197,6 +200,7 @@ class stellafr_state : public driver_device m_duart(*this, "duart"), m_nvram(*this, "nvram"), m_dac(*this, "dac"), + m_st(*this, "st"), m_digits(*this, "digit%u", 0U), m_lamps(*this, "lamp%u", 0U), m_leds(*this, "led%u", 0U), @@ -214,6 +218,7 @@ class stellafr_state : public driver_device required_device m_duart; required_device m_nvram; required_device m_dac; + required_device m_st; output_finder<8> m_digits; output_finder<128> m_lamps; output_finder<2> m_leds; @@ -228,6 +233,8 @@ class stellafr_state : public driver_device uint8_t m_anz2; uint8_t m_mux2; + bool m_outst; + uint8_t mux_r(); void mux_w(uint8_t data); void mux2_w(uint8_t data); @@ -235,6 +242,8 @@ class stellafr_state : public driver_device void ay8910_portb_w(uint8_t data); void lamps_w(uint8_t row, uint16_t data); + void st_in(uint8_t data); + void mem_map(address_map &map) ATTR_COLD; void fc7_map(address_map &map) ATTR_COLD; @@ -246,7 +255,6 @@ uint8_t stellafr_state::mux_r() bool li = false; bool emp = false; bool ma = false; - bool st = false; bool t = false; // main buttons in bool t2 = false; bool emp2 = false; @@ -257,7 +265,7 @@ uint8_t stellafr_state::mux_r() if (li) data |= (1 << U10_OUTLI); if (emp) data |= (1 << U10_OUTEMP); if (ma) data |= (1 << U10_OUTMA); - if (st) data |= (1 << U10_OUTST); + if (m_outst) data |= (1 << U10_OUTST); if (t) data |= (1 << U10_OUTT); if (t2) data |= (1 << U10_OUTT2); if (emp2) data |= (1 << U10_EMP2); @@ -277,6 +285,11 @@ void stellafr_state::lamps_w(uint8_t row, uint16_t data) } } +void stellafr_state::st_in(uint8_t data) +{ + m_outst = data; +} + void stellafr_state::mux_w(uint8_t data) { bool enma1 = BIT(data,U5_EN1MA); @@ -308,6 +321,8 @@ void stellafr_state::mux_w(uint8_t data) ; if (aw2) ; + + m_st->write_dtr(enanz1); } void stellafr_state::mux2_w(uint8_t data) @@ -322,6 +337,8 @@ void stellafr_state::mux2_w(uint8_t data) m_mux1 = (m_mux1 << 1) | BIT(data,U1_MUX1); m_anz2 = (m_anz2 << 1) | BIT(data,U1_ANZ2); m_mux2 = (m_mux2 << 1) | BIT(data,U1_MUX2); + + m_st->write_txd(m_ma1); } void stellafr_state::duart_output_w(uint8_t data) @@ -392,6 +409,9 @@ void stellafr_state::stellafr(machine_config &config) AD7224(config, m_dac, 0); + RS232_PORT(config, m_st, default_rs232_devices, nullptr); + m_st->rxd_handler().set(FUNC(stellafr_state::st_in)); + SPEAKER(config, "mono").front_center(); ay8910_device &aysnd(AY8910(config, "aysnd", 1000000)); aysnd.add_route(ALL_OUTPUTS, "mono", 0.85); diff --git a/src/mame/layout/servicet.lay b/src/mame/layout/servicet.lay new file mode 100644 index 0000000000000..e7971b608f9fd --- /dev/null +++ b/src/mame/layout/servicet.lay @@ -0,0 +1,133 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +