diff --git a/scripts/src/cpu.lua b/scripts/src/cpu.lua index f94d68645d1ae..4ad682c314046 100644 --- a/scripts/src/cpu.lua +++ b/scripts/src/cpu.lua @@ -3012,6 +3012,8 @@ if CPUS["TLCS900"] then MAME_DIR .. "src/devices/cpu/tlcs900/900htbl.hxx", MAME_DIR .. "src/devices/cpu/tlcs900/tmp94c241.cpp", MAME_DIR .. "src/devices/cpu/tlcs900/tmp94c241.h", + MAME_DIR .. "src/devices/cpu/tlcs900/tmp94c241_serial.cpp", + MAME_DIR .. "src/devices/cpu/tlcs900/tmp94c241_serial.h", MAME_DIR .. "src/devices/cpu/tlcs900/tmp95c061.cpp", MAME_DIR .. "src/devices/cpu/tlcs900/tmp95c061.h", MAME_DIR .. "src/devices/cpu/tlcs900/tmp95c063.cpp", diff --git a/src/devices/cpu/tlcs900/tmp94c241.cpp b/src/devices/cpu/tlcs900/tmp94c241.cpp index 5e22cd38efad3..95acf0735d68f 100644 --- a/src/devices/cpu/tlcs900/tmp94c241.cpp +++ b/src/devices/cpu/tlcs900/tmp94c241.cpp @@ -17,28 +17,6 @@ // device type definition DEFINE_DEVICE_TYPE(TMP94C241, tmp94c241_device, "tmp94c241", "Toshiba TMP94C241") -enum -{ - INTE45, - INTE67, - INTE89, - INTEAB, - INTET01, - INTET23, - INTET45, - INTET67, - INTET89, - INTETAB, - INTES0, - INTES1, - INTETC01, - INTETC23, - INTETC45, - INTETC67, - INTE0AD, - INTNMWDT -}; - static const struct { uint8_t reg; uint8_t iff; @@ -122,9 +100,6 @@ tmp94c241_device::tmp94c241_device(const machine_config &mconfig, const char *ta m_t16_cap{ 0, 0, 0, 0, 0, 0, 0, 0 }, m_timer_16{ 0, 0, 0, 0 }, m_watchdog_mode(0), - m_serial_control{ 0, 0 }, - m_serial_mode{ 0, 0 }, - m_baud_rate{ 0, 0 }, m_od_enable(0), m_ad_mode1(0), m_ad_mode2(0), @@ -138,7 +113,8 @@ tmp94c241_device::tmp94c241_device(const machine_config &mconfig, const char *ta m_mamr{ 0, 0, 0, 0, 0, 0 }, m_dram_refresh{ 0, 0 }, m_dram_access{ 0, 0 }, - m_da_drive(0) + m_da_drive(0), + m_serial(*this, "serial%u", 0U) { } @@ -194,9 +170,6 @@ void tmp94c241_device::device_start() save_item(NAME(m_taffcr)); save_item(NAME(m_t16run)); save_item(NAME(m_watchdog_mode)); - save_item(NAME(m_serial_control)); - save_item(NAME(m_serial_mode)); - save_item(NAME(m_baud_rate)); save_item(NAME(m_od_enable)); save_item(NAME(m_ad_mode1)); save_item(NAME(m_ad_mode2)); @@ -279,12 +252,6 @@ void tmp94c241_device::device_reset() std::fill_n(&m_timer_8[0], 4, 0x00); std::fill_n(&m_timer_16[0], 4, 0x00); m_watchdog_mode = 0x80; - for (int i = 0; i < 2; i++) - { - m_serial_control[i] &= 0x80; - m_serial_mode[i] &= 0x80; - m_baud_rate[i] = 0x00; - } m_od_enable = 0x00; m_ad_mode1 = 0x00; m_ad_mode2 = 0x00; @@ -303,6 +270,10 @@ void tmp94c241_device::device_reset() std::fill_n(&m_dram_refresh[0], 2, 0x00); std::fill_n(&m_dram_access[0], 2, 0x80); m_da_drive = 0x00; + + m_int_reg[INTES0] |= 0x80; + m_int_reg[INTES1] |= 0x80; + m_check_irqs = 1; } uint8_t tmp94c241_device::inte_r(offs_t offset) @@ -695,61 +666,6 @@ void tmp94c241_device::wdcr_w(uint8_t data) { } -template -uint8_t tmp94c241_device::scNbuf_r() -{ - return 0; -} - -template -void tmp94c241_device::scNbuf_w(uint8_t data) -{ - // Fake finish sending data - m_int_reg[(Channel == 0) ? INTES0 : INTES1] |= 0x80; - m_check_irqs = 1; - logerror("sc%dbuf write: %02X\n", Channel, data); - //machine().debugger().debug_break(); -} - -template -uint8_t tmp94c241_device::scNcr_r() -{ - uint8_t reg = m_serial_control[Channel]; - if (!machine().side_effects_disabled()) - m_serial_control[Channel] &= 0xe3; - return reg; -} - -template -void tmp94c241_device::scNcr_w(uint8_t data) -{ - m_serial_control[Channel] = data; -} - -template -uint8_t tmp94c241_device::scNmod_r() -{ - return m_serial_mode[Channel]; -} - -template -void tmp94c241_device::scNmod_w(uint8_t data) -{ - m_serial_mode[Channel] = data; -} - -template -uint8_t tmp94c241_device::brNcr_r() -{ - return m_baud_rate[Channel]; -} - -template -void tmp94c241_device::brNcr_w(uint8_t data) -{ - m_baud_rate[Channel] = data; -} - uint8_t tmp94c241_device::ode_r() { return m_od_enable; @@ -842,9 +758,20 @@ void tmp94c241_device::port_cr_w(uint8_t data) template void tmp94c241_device::port_fc_w(uint8_t data) { + if (P == PORT_F) + { + logerror("PORT FUNCTION F: %02X\n", data); + } m_port_function[P] = data; } +void tmp94c241_device::device_add_mconfig(machine_config &mconfig) +{ + TMP94C241_SERIAL(mconfig, m_serial[0], 0, DERIVED_CLOCK(1, 1)); + TMP94C241_SERIAL(mconfig, m_serial[1], 1, DERIVED_CLOCK(1, 1)); +} + + //************************************************************************** // INTERNAL REGISTERS //************************************************************************** @@ -939,14 +866,14 @@ void tmp94c241_device::internal_mem(address_map &map) map(0x0000c6, 0x0000c7).r(FUNC(tmp94c241_device::cap_r)); map(0x0000c8, 0x0000c8).rw(FUNC(tmp94c241_device::tamod_r), FUNC(tmp94c241_device::tamod_w)); map(0x0000c9, 0x0000c9).rw(FUNC(tmp94c241_device::taffcr_r), FUNC(tmp94c241_device::taffcr_w)); - map(0x0000d0, 0x0000d0).rw(FUNC(tmp94c241_device::scNbuf_r<0>), FUNC(tmp94c241_device::scNbuf_w<0>)); - map(0x0000d1, 0x0000d1).rw(FUNC(tmp94c241_device::scNcr_r<0>), FUNC(tmp94c241_device::scNcr_w<0>)); - map(0x0000d2, 0x0000d2).rw(FUNC(tmp94c241_device::scNmod_r<0>), FUNC(tmp94c241_device::scNmod_w<0>)); - map(0x0000d3, 0x0000d3).rw(FUNC(tmp94c241_device::brNcr_r<0>), FUNC(tmp94c241_device::brNcr_w<0>)); - map(0x0000d4, 0x0000d4).rw(FUNC(tmp94c241_device::scNbuf_r<1>), FUNC(tmp94c241_device::scNbuf_w<1>)); - map(0x0000d5, 0x0000d5).rw(FUNC(tmp94c241_device::scNcr_r<1>), FUNC(tmp94c241_device::scNcr_w<1>)); - map(0x0000d6, 0x0000d6).rw(FUNC(tmp94c241_device::scNmod_r<1>), FUNC(tmp94c241_device::scNmod_w<1>)); - map(0x0000d7, 0x0000d7).rw(FUNC(tmp94c241_device::brNcr_r<1>), FUNC(tmp94c241_device::brNcr_w<1>)); + map(0x0000d0, 0x0000d0).rw(m_serial[0], FUNC(tmp94c241_serial_device::scNbuf_r), FUNC(tmp94c241_serial_device::scNbuf_w)); + map(0x0000d1, 0x0000d1).rw(m_serial[0], FUNC(tmp94c241_serial_device::scNcr_r), FUNC(tmp94c241_serial_device::scNcr_w)); + map(0x0000d2, 0x0000d2).rw(m_serial[0], FUNC(tmp94c241_serial_device::scNmod_r), FUNC(tmp94c241_serial_device::scNmod_w)); + map(0x0000d3, 0x0000d3).rw(m_serial[0], FUNC(tmp94c241_serial_device::brNcr_r), FUNC(tmp94c241_serial_device::brNcr_w)); + map(0x0000d4, 0x0000d4).rw(m_serial[1], FUNC(tmp94c241_serial_device::scNbuf_r), FUNC(tmp94c241_serial_device::scNbuf_w)); + map(0x0000d5, 0x0000d5).rw(m_serial[1], FUNC(tmp94c241_serial_device::scNcr_r), FUNC(tmp94c241_serial_device::scNcr_w)); + map(0x0000d6, 0x0000d6).rw(m_serial[1], FUNC(tmp94c241_serial_device::scNmod_r), FUNC(tmp94c241_serial_device::scNmod_w)); + map(0x0000d7, 0x0000d7).rw(m_serial[1], FUNC(tmp94c241_serial_device::brNcr_r), FUNC(tmp94c241_serial_device::brNcr_w)); map(0x0000e0, 0x0000f0).rw(FUNC(tmp94c241_device::inte_r), FUNC(tmp94c241_device::inte_w)); map(0x0000f6, 0x0000f6).w(FUNC(tmp94c241_device::iimc_w)); map(0x0000f7, 0x0000f7).rw(FUNC(tmp94c241_device::intnmwdt_r), FUNC(tmp94c241_device::intnmwdt_w)); @@ -1123,10 +1050,17 @@ void tmp94c241_device::tlcs900_handle_timers() uint8_t operating_mode, bool invert) { + bool match; for ( ; m_timer_change[timer_index] > 0; m_timer_change[timer_index]--) { m_timer_8[timer_index]++; - if (m_timer_8[timer_index] == m_treg_8[timer_reg]) + match = m_timer_8[timer_index] == m_treg_8[timer_reg]; + if (timer_index == 1) + { + m_serial[0]->TO2_trigger(match); + m_serial[1]->TO2_trigger(match); + } + if (match) { if (BIT(timer_index, 0) == 0) { diff --git a/src/devices/cpu/tlcs900/tmp94c241.h b/src/devices/cpu/tlcs900/tmp94c241.h index bb83a748f735c..70235722c1dd8 100644 --- a/src/devices/cpu/tlcs900/tmp94c241.h +++ b/src/devices/cpu/tlcs900/tmp94c241.h @@ -12,7 +12,29 @@ #pragma once #include "tlcs900.h" +#include "tmp94c241_serial.h" +enum +{ + INTE45, + INTE67, + INTE89, + INTEAB, + INTET01, + INTET23, + INTET45, + INTET67, + INTET89, + INTETAB, + INTES0, + INTES1, + INTETC01, + INTETC23, + INTETC45, + INTETC67, + INTE0AD, + INTNMWDT +}; //************************************************************************** // TYPE DEFINITIONS @@ -22,6 +44,8 @@ class tmp94c241_device : public tlcs900h_device { + friend class tmp94c241_serial_device; + static constexpr uint8_t PORT_0 = 0; // 8 bit I/O. Shared with d0-d7 static constexpr uint8_t PORT_1 = 1; // 8 bit I/O. Shared with d8-d15 static constexpr uint8_t PORT_2 = 2; // 8 bit I/O. Shared with d16-d23 @@ -111,6 +135,7 @@ class tmp94c241_device : public tlcs900h_device virtual void device_resolve_objects() override ATTR_COLD; virtual void device_start() override ATTR_COLD; virtual void device_reset() override ATTR_COLD; + virtual void device_add_mconfig(machine_config &config) override ATTR_COLD; // device_execute_interface overrides virtual void execute_set_input(int inputnum, int state) override; @@ -243,10 +268,7 @@ class tmp94c241_device : public tlcs900h_device // Watchdog Timer uint8_t m_watchdog_mode; - // Serial Channel - uint8_t m_serial_control[2]; - uint8_t m_serial_mode[2]; - uint8_t m_baud_rate[2]; + // Serial Channels uint8_t m_od_enable; // A/D Converter Control @@ -271,6 +293,9 @@ class tmp94c241_device : public tlcs900h_device // D/A Converter Control uint8_t m_da_drive; + +public: + required_device_array m_serial; }; // device type declaration diff --git a/src/devices/cpu/tlcs900/tmp94c241_serial.cpp b/src/devices/cpu/tlcs900/tmp94c241_serial.cpp new file mode 100644 index 0000000000000..2bf9266f765da --- /dev/null +++ b/src/devices/cpu/tlcs900/tmp94c241_serial.cpp @@ -0,0 +1,225 @@ +// license:BSD-3-Clause +// copyright-holders:Felipe Sanches +/*************************************************************************** + + TOSHIBA TLCS900 - TMP94C241 SERIAL + +***************************************************************************/ + +#include "emu.h" +#include "tmp94c241.h" +#include "tmp94c241_serial.h" + +#include "logmacro.h" + +DEFINE_DEVICE_TYPE(TMP94C241_SERIAL, tmp94c241_serial_device, "tmp94c241_serial", "TMP94C241 Serial Channel") + +tmp94c241_serial_device::tmp94c241_serial_device(const machine_config &mconfig, const char *tag, device_t *owner, uint8_t channel, uint32_t clock) : + device_t(mconfig, TMP94C241_SERIAL, tag, owner, clock), + m_channel(channel), + m_serial_control(0), + m_serial_mode(0), /* I/O interface mode and clock source at TO2 trigger */ + m_baud_rate(0), + m_hz(0), + m_clock_count(0), + m_tx_shift_register(0), + m_serial_in(0), + m_serial_in_prev(0), + m_sck_in(0), + m_serial_out(0), + m_sck_out(0), + m_serial_out_cb(*this), + m_sck_cb(*this) +{ +} + +void tmp94c241_serial_device::device_start() +{ + m_tx_timer = timer_alloc(FUNC(tmp94c241_serial_device::tx_timer_callback), this); + m_cpu = dynamic_cast(owner()); + + save_item(NAME(m_serial_control)); + save_item(NAME(m_serial_mode)); + save_item(NAME(m_baud_rate)); + save_item(NAME(m_hz)); + save_item(NAME(m_clock_count)); + save_item(NAME(m_tx_shift_register)); + save_item(NAME(m_serial_in)); + save_item(NAME(m_serial_in_prev)); + save_item(NAME(m_sck_in)); + save_item(NAME(m_serial_out)); + save_item(NAME(m_sck_out)); + + m_sck_cb(m_sck_out); + m_serial_out_cb(m_serial_out); +} + +void tmp94c241_serial_device::device_reset() +{ + m_serial_control &= 0x80; + m_serial_mode &= 0x80; + m_baud_rate = 0x00; +} + +void tmp94c241_serial_device::TO2_trigger(int state) +{ +// logerror("TO2_trigger state=%d\n", state); + if ((m_serial_mode & 3) == 0 && BIT(m_serial_control, 1)) + { + /* Clock source: TO2 output compare trigger */ + sck(state); + } +} + +void tmp94c241_serial_device::sck(int state) +{ + if (m_sck_in != state) + { + m_sck_in = state; + // logerror("sck state=%d\n", state); + + update_serial(); + } +} + +void tmp94c241_serial_device::serial_in(int state) +{ + if (m_serial_in != state) + { + m_serial_in = state; + + update_serial(); + } +} + +uint8_t tmp94c241_serial_device::scNbuf_r() +{ + return 0; +} + +void tmp94c241_serial_device::scNbuf_w(uint8_t data) +{ + logerror("buf write: %02X\n", data); + m_tx_shift_register = data; + m_clock_count = 8; + //if (m_channel == 1) machine().debug_break(); +} + +uint8_t tmp94c241_serial_device::scNcr_r() +{ + return m_serial_control; +} + +void tmp94c241_serial_device::scNcr_w(uint8_t data) +{ + m_serial_control = data; +} + +uint8_t tmp94c241_serial_device::scNmod_r() +{ + return m_serial_mode; +} + +void tmp94c241_serial_device::scNmod_w(uint8_t data) +{ + switch((data >> 2) & 3) + { + case 0: logerror("I/O interface mode\n"); break; + case 1: logerror("7-bit uart mode (Not implemented yet)\n"); break; + case 2: logerror("8-bit uart mode (Not implemented yet)\n"); break; + case 3: logerror("9-bit uart mode (Not implemented yet)\n"); break; + } + switch(data & 3) + { + case 0: logerror("clk source: TO2 trigger\n"); break; + case 1: logerror("clk source: Baud rate generator (Not implemented yet)\n"); break; + case 2: logerror("clk source: Internal clock at ϕ1 (Not implemented yet)\n"); break; + case 3: logerror("clk source: external clock (SCLK%d) (Not implemented yet)\n", m_channel); break; + } + m_serial_mode = data; + m_cpu->m_int_reg[(m_channel == 0) ? INTES0 : INTES1] |= 0x80; + m_cpu->m_check_irqs = 1; +} + +uint8_t tmp94c241_serial_device::brNcr_r() +{ + return m_baud_rate; +} + +void tmp94c241_serial_device::brNcr_w(uint8_t data) +{ + m_baud_rate = data; + uint8_t divisor = data & 0x0f; + uint8_t input_clocks[] = {0, 2, 8, 32}; + uint8_t shift_amount = (((data >> 4) & 3) + 1) * 2; + logerror("baud rate: Divisor=%d Internal Clock T%d\n", divisor, input_clocks[(data >> 4) & 3]); + if (divisor) + { + long int fc = 16'000'000; // TODO: set this from the cpu. + m_hz = (fc >> shift_amount) / divisor; + m_tx_timer->adjust(attotime::from_hz(m_hz), 0, attotime::from_hz(m_hz)); + logerror("tx_timer set to %d Hz.\n", m_hz); + } else { + m_tx_timer->reset(attotime::never); + m_hz = 0; + logerror("tx_timer disabled.\n"); + } + //if (m_channel == 1) machine().debug_break(); +} + +void tmp94c241_serial_device::update_serial() +{ + //logerror("update_serial sck=%d serial_in=%d m_clock_count=%d\n", m_sck_in, m_serial_in, m_clock_count); + if (m_clock_count){ + logerror("send bit #%d: %d\n", 8-m_clock_count, m_tx_shift_register & 1); + + m_serial_out_cb(m_tx_shift_register & 1); + m_sck_cb(1); + m_sck_cb(0); + m_tx_shift_register >>= 1; + if (--m_clock_count == 0) { + logerror("Finished sending byte.\n"); + // We finished sending the data: + m_cpu->m_int_reg[(m_channel == 0) ? INTES0 : INTES1] |= 0x80; + m_cpu->m_check_irqs = 1; + } + } +} + +/* +reset: +... +ef03d8: 08 3f 73 ld (0x3f),0x73 + + +Reached from which routine ?: +... +fc4068: c1 8f 8d 3e 50 or (0x8d8f),0x50 +fc406d: c1 8f 8d 21 ld A,(0x8d8f) +fc4071: f0 3f 41 ld (0x3f),A + + +SERIAL_METHOD_2: ; FC45A8 +... +fc45ab: c1 8f 8d 3e 50 or (0x8d8f),0x50 +fc45b0: c1 8f 8d 21 ld A,(0x8d8f) +fc45b4: f0 3f 41 ld (0x3f),A + +SERIAL_METHOD_4: ; FC460D +... +fc4610: c1 8f 8d 3e 50 or (0x8d8f),0x50 +fc4615: c1 8f 8d 21 ld A,(0x8d8f) +fc4619: f0 3f 41 ld (0x3f),A + + +*/ + +TIMER_CALLBACK_MEMBER(tmp94c241_serial_device::tx_timer_callback) +{ + if (m_hz && m_clock_count && (m_cpu->m_port_function[PORT_F] & (1 << (m_channel==0 ? 2: 6)))) + { + //logerror("m_clock_count=%d and we'll call sck(%d).\n", m_clock_count, m_sck_in ^ 1); + sck(m_sck_in ^ 1); + } +} + diff --git a/src/devices/cpu/tlcs900/tmp94c241_serial.h b/src/devices/cpu/tlcs900/tmp94c241_serial.h new file mode 100644 index 0000000000000..ac2008c5af6de --- /dev/null +++ b/src/devices/cpu/tlcs900/tmp94c241_serial.h @@ -0,0 +1,72 @@ +// license:BSD-3-Clause +// copyright-holders:Felipe Sanches +/*************************************************************************** + + TOSHIBA TLCS900 - TMP94C241 SERIAL + +***************************************************************************/ + +#ifndef MAME_CPU_TMP94C241_SERIAL_H +#define MAME_CPU_TMP94C241_SERIAL_H + +#pragma once + +class tmp94c241_device; + +class tmp94c241_serial_device : + public device_t +{ + static constexpr uint8_t PORT_F = 14; // 6 bit I/O. Shared with I/O functions of serial interface + +public: + tmp94c241_serial_device(const machine_config &mconfig, const char *tag, device_t *owner, uint8_t channel, uint32_t clock = 0); + + void TO2_trigger(int state); + void serial_in(int state); + auto serial_out() { return m_serial_out_cb.bind(); } + void sck(int state); + auto sck() { return m_sck_cb.bind(); } + + uint8_t brNcr_r(); + void brNcr_w(uint8_t data); + void scNmod_w(uint8_t data); + uint8_t scNmod_r(); + void scNcr_w(uint8_t data); + uint8_t scNcr_r(); + void scNbuf_w(uint8_t data); + uint8_t scNbuf_r(); + +protected: + // device_t + virtual void device_start() override ATTR_COLD; + virtual void device_reset() override ATTR_COLD; + + void update_serial(); + TIMER_CALLBACK_MEMBER(tx_timer_callback); + + emu_timer *m_tx_timer; + + uint8_t m_channel; + uint8_t m_serial_control; + uint8_t m_serial_mode; + uint8_t m_baud_rate; + uint32_t m_hz; + + uint8_t m_clock_count; + uint8_t m_tx_shift_register; + uint8_t m_serial_in; + uint8_t m_serial_in_prev; + uint8_t m_sck_in; + + uint8_t m_serial_out; + uint8_t m_sck_out; + + devcb_write_line m_serial_out_cb; + devcb_write_line m_sck_cb; + + tmp94c241_device *m_cpu; +}; + +DECLARE_DEVICE_TYPE(TMP94C241_SERIAL, tmp94c241_serial_device) + +#endif // MAME_CPU_TMP94C241_SERIAL_H diff --git a/src/mame/matsushita/kn5000.cpp b/src/mame/matsushita/kn5000.cpp index 751f369e40dc7..23f62aef08c42 100644 --- a/src/mame/matsushita/kn5000.cpp +++ b/src/mame/matsushita/kn5000.cpp @@ -8,6 +8,7 @@ #include "emu.h" #include "bus/technics/kn5000/hdae5000.h" +#include "bus/midi/midi.h" #include "cpu/tlcs900/tmp94c241.h" #include "imagedev/floppy.h" #include "machine/gen_latch.h" @@ -15,6 +16,7 @@ #include "video/pc_vga.h" #include "screen.h" #include "kn5000.lh" +#include "kn5000_cpanel.h" class mn89304_vga_device : public svga_device { @@ -91,6 +93,7 @@ class kn5000_state : public driver_device public: kn5000_state(const machine_config &mconfig, device_type type, const char *tag) : driver_device(mconfig, type, tag) + , m_cpanel(*this, "cpanel") , m_maincpu(*this, "maincpu") , m_subcpu(*this, "subcpu") , m_maincpu_latch(*this, "maincpu_latch") @@ -112,6 +115,7 @@ class kn5000_state : public driver_device void kn5000(machine_config &config); private: + required_device m_cpanel; required_device m_maincpu; required_device m_subcpu; required_device m_maincpu_latch; @@ -728,8 +732,18 @@ void kn5000_state::kn5000(machine_config &config) // RX0/TX0 = MRXD/MTXD + auto &mdin(MIDI_PORT(config, "mdin")); + midiin_slot(mdin); + mdin.rxd_handler().set(m_maincpu->m_serial[0], FUNC(tmp94c241_serial_device::serial_in)); + + // TODO: MIDI output + // midiout_slot(MIDI_PORT(config, "mdout")); + // RX1/TX1 = CPDATA - // SCLK1 = CPSCK + // SCLK1 = CPSCK + auto &m_cpanel(KN5000_CPANEL(config, "cpanel")); + m_maincpu->m_serial[1].lookup()->serial_out().set(m_cpanel, FUNC(kn5000_cpanel_device::serial_in)); + m_maincpu->m_serial[1].lookup()->sck().set(m_cpanel, FUNC(kn5000_cpanel_device::sck_in)); // AN0 = EXP (expression pedal?) // AN1 = AFT diff --git a/src/mame/matsushita/kn5000_cpanel.cpp b/src/mame/matsushita/kn5000_cpanel.cpp new file mode 100644 index 0000000000000..a08751000cea2 --- /dev/null +++ b/src/mame/matsushita/kn5000_cpanel.cpp @@ -0,0 +1,88 @@ +// license:GPL2+ +// copyright-holders:Felipe Sanches +/*************************************************************************** + + KN5000 control panel + +***************************************************************************/ + +#include "emu.h" +#include "kn5000_cpanel.h" + +#include "logmacro.h" + +DEFINE_DEVICE_TYPE(KN5000_CPANEL, kn5000_cpanel_device, "kn5000_cpanel", "KN5000 Control Panel") + +kn5000_cpanel_device::kn5000_cpanel_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + device_t(mconfig, KN5000_CPANEL, tag, owner, clock), + m_sck_cb(*this), + m_sck_in(1), + m_sck_out(1), + m_clock_count(0), + m_tx_shift_register(0), + m_rx_shift_register(0) +{ +} + +void kn5000_cpanel_device::device_start() +{ + save_item(NAME(m_sck_in)); + save_item(NAME(m_sck_in_prev)); + save_item(NAME(m_sck_out)); + save_item(NAME(m_serial_in)); + save_item(NAME(m_clock_count)); + save_item(NAME(m_tx_shift_register)); + save_item(NAME(m_rx_shift_register)); + + m_sck_cb(m_sck_out); + sck_in(0); + serial_in(0); + + update_serial(); +} + +void kn5000_cpanel_device::device_reset() +{ + update_serial(); +} + +void kn5000_cpanel_device::sck_in(int state) +{ + if (m_sck_in != state) + { + m_sck_in_prev = m_sck_in; + m_sck_in = state; + + // logerror("sck_in state=%d\n", state); + update_serial(); + } +} + +void kn5000_cpanel_device::serial_in(int state) +{ + if (m_serial_in != state) + { + m_serial_in = state; + +// logerror("serial_in state=%d\n", state); + update_serial(); + } +} + + +void kn5000_cpanel_device::update_serial() +{ + if (m_sck_in != m_sck_in_prev && m_sck_in == 1) + { + m_rx_shift_register >>= 1; + m_rx_shift_register |= (m_serial_in << 7); + + logerror(" rx bit #%d: %d cur_value=%02X\n", m_clock_count, m_serial_in, m_rx_shift_register); + + if (++m_clock_count == 8) + { + logerror(" Received: %02X\n", m_rx_shift_register); + m_clock_count = 0; + } + } +} diff --git a/src/mame/matsushita/kn5000_cpanel.h b/src/mame/matsushita/kn5000_cpanel.h new file mode 100644 index 0000000000000..20db8b2c18802 --- /dev/null +++ b/src/mame/matsushita/kn5000_cpanel.h @@ -0,0 +1,46 @@ +// license:GPL2+ +// copyright-holders:Felipe Sanches +/*************************************************************************** + + KN5000 control panel + +***************************************************************************/ + +#ifndef MAME_CPU_KN5000_CPANEL_H +#define MAME_CPU_KN5000_CPANEL_H + +#pragma once + +class kn5000_cpanel_device : + public device_t +{ +public: + kn5000_cpanel_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0); + +// auto sck() { return m_sck_cb.bind(); } + void sck_in(int state); + void serial_in(int state); + + +protected: + // device_t + virtual void device_start() override ATTR_COLD; + virtual void device_reset() override ATTR_COLD; + + void update_serial(); + + int8_t m_serial_in; + + devcb_write_line m_sck_cb; + + int8_t m_sck_in; + int8_t m_sck_in_prev; + int8_t m_sck_out; + uint8_t m_clock_count; + uint8_t m_tx_shift_register; + uint8_t m_rx_shift_register; +}; + +DECLARE_DEVICE_TYPE(KN5000_CPANEL, kn5000_cpanel_device) + +#endif // MAME_CPU_KN5000_CPANEL_H