From 035d49869d823e3047b5aaf5e30faf2f93a43d3a Mon Sep 17 00:00:00 2001 From: Mark Garlanger Date: Wed, 24 Jan 2024 01:56:27 -0600 Subject: machine/s2350.cpp: Added AMI S2350 USRT device. (#11959) Frame format configuration is not implemented yet. --- scripts/src/machine.lua | 12 ++ src/devices/machine/s2350.cpp | 414 ++++++++++++++++++++++++++++++++++++++++++ src/devices/machine/s2350.h | 119 ++++++++++++ 3 files changed, 545 insertions(+) create mode 100644 src/devices/machine/s2350.cpp create mode 100644 src/devices/machine/s2350.h diff --git a/scripts/src/machine.lua b/scripts/src/machine.lua index af09e563671..87d88dc077c 100644 --- a/scripts/src/machine.lua +++ b/scripts/src/machine.lua @@ -3204,6 +3204,18 @@ if (MACHINES["RTC9701"]~=null) then } end +--------------------------------------------------- +-- +--@src/devices/machine/s2350.h,MACHINES["S2350"] = true +--------------------------------------------------- + +if (MACHINES["S2350"]~=null) then + files { + MAME_DIR .. "src/devices/machine/s2350.cpp", + MAME_DIR .. "src/devices/machine/s2350.h", + } +end + --------------------------------------------------- -- --@src/devices/machine/s2636.h,MACHINES["S2636"] = true diff --git a/src/devices/machine/s2350.cpp b/src/devices/machine/s2350.cpp new file mode 100644 index 00000000000..06370b5f340 --- /dev/null +++ b/src/devices/machine/s2350.cpp @@ -0,0 +1,414 @@ +// license:BSD-3-Clause +// copyright-holders:Mark Garlanger +/*************************************************************************** + + American Microsystems, Inc. (AMI) S2350 Universal Synchronous Receiver/Transmitter(USRT) + + Chip Features + - 500kHz Data Rates + - Internal Sync Detection + - Fill Character Register + - Double Buffered Input/Output + - Bus Oriented Outputs + - 5-8 Bit Characters + - Odd/Even or No Parity + - Error Status Flags + + + Current assumptions: + - Data size == 8 + - Parity == NONE + + Not Implemented + - parity + - data size (other than 8) + + ********************************************************************** + _____ _____ + GND 1 |* \_/ | 40 NDB2 + Vcc 2 | | 39 NDB1 + NPB 3 | | 38 TDS + POE 4 | | 37 RCP + CS 5 | | 36 TCP + TSO 6 | | 35 RDE + FCT 7 | | 34 SWE + SCR 8 | | 33 RD0 + TBMT 9 | AMI | 32 RD1 + RPE 10 | S2350 | 31 RD2 + ROR 11 | | 30 RD3 + RDA 12 | | 29 RD4 + RR 13 | | 28 RD5 + RESET 14 | | 27 RD6 + D0 15 | | 26 RD7 + D1 16 | | 25 RSI + D2 17 | | 24 TFS + D3 18 | | 23 RSS + D4 19 | | 22 D7 + D5 20 |_____________| 21 D6 + + +Name Pin No. Function +---------------------------------------------------------------------- + +D0-D7 15-22 Data Inputs + +RD7-RD70 26-33 Received Data Outputs + +TDS 38 Transmit Data Strobe + +TFS 24 Transmit Fill Strobe + +RSS 23 Receiver Sync Strobe + +TBMT 9 Transmit Buffer Empty + +TSO 6 Transmitter Serial Output + +TCP 36 Transmit Clock + +RDE 35 Receive Data Enable + +FCT 7 Fill Character Transmitted + +RSI 25 Receiver Serial Input + +RCP 37 Receiver Clock + +RDA 12 Received Data Available + +SCR 8 Sync Character Received + +SWE 34 Status Word Enable + +ROR 11 Receiver Overrun + +RPE 10 Receiver Parity Error + +RR 13 Receiver Restart + +NDB1/NDB2 39-40 Number Data Bits + +NPB 3 No Parity Bit + +POE 4 Parity Odd/Even + +CS 5 Control Strobe + +RESET 14 Master Reset + +Vcc 2 +5.0V + +GND 1 Ground +***************************************************************************/ + + +#include "emu.h" +#include "s2350.h" + +// Shows register setup +#define LOG_REG (1U << 1) +// Show control lines +#define LOG_LINE (1U << 2) +// Function calls +#define LOG_FUNC (1U << 3) +// Sync detect +#define LOG_SYNC (1U << 4) + +//#define VERBOSE (0xff) + +#include "logmacro.h" + +#define LOGREG(...) LOGMASKED(LOG_REG, __VA_ARGS__) +#define LOGLINE(...) LOGMASKED(LOG_LINE, __VA_ARGS__) +#define LOGFUNC(...) LOGMASKED(LOG_FUNC, __VA_ARGS__) +#define LOGSYNC(...) LOGMASKED(LOG_SYNC, __VA_ARGS__) + +#ifdef _MSC_VER +#define FUNCNAME __func__ +#else +#define FUNCNAME __PRETTY_FUNCTION__ +#endif + + +DEFINE_DEVICE_TYPE(S2350, s2350_device, "s2350", "American Microsystems Inc. S2350 USRT") + + +s2350_device::s2350_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : + device_t(mconfig, S2350, tag, owner, clock), + m_tbmt(*this), + m_fct(*this), + m_tx_cb(*this), + m_rda(*this), + m_scr(*this), + m_ror(*this), + m_rpe(*this) +{ +} + +void s2350_device::device_start() +{ + save_item(NAME(m_transmit_buffer_empty)); + save_item(NAME(m_fill_char_transmitted)); + save_item(NAME(m_transmitter_holding_reg)); + save_item(NAME(m_transmitter_fill_reg)); + save_item(NAME(m_transmitter_shift_reg)); + save_item(NAME(m_serial_tx_state)); + + save_item(NAME(m_received_data_available)); + save_item(NAME(m_receiver_overrun)); + save_item(NAME(m_receiver_parity_error)); + save_item(NAME(m_sync_character_received)); + + save_item(NAME(m_receiver_output_reg)); + save_item(NAME(m_receiver_sync_reg)); + save_item(NAME(m_receiver_shift_reg)); + save_item(NAME(m_serial_rx_state)); + + save_item(NAME(m_in_sync)); +} + +void s2350_device::device_reset() +{ + // transmitter flags + set_transmit_buffer_empty(true); + set_fill_char_transmitted(false); + + // transmitter registers + m_transmitter_shift_reg = 0xff; + m_transmitter_holding_reg = 0xff; + m_transmitter_fill_reg = 0x00; + + m_serial_tx_state = 0; + + set_received_data_available(false); + set_receiver_overrun(false); + set_receiver_parity_error(false); + set_sync_character_received(false); + + m_sync_search_active = false; + m_in_sync = false; + + m_serial_rx_state = 0; + + // receiver registers + m_receiver_output_reg = 0x00; + m_receiver_sync_reg = 0x00; + m_receiver_shift_reg = 0x00; +} + +void s2350_device::transmitter_holding_reg_w(u8 data) +{ + LOGREG("%s: 0x%02x\n", FUNCNAME, data); + + m_transmitter_holding_reg = data; + set_transmit_buffer_empty(false); +} + +void s2350_device::transmit_fill_reg_w(u8 data) +{ + LOGREG("%s: 0x%02x\n", FUNCNAME, data); + + m_transmitter_fill_reg = data; +} + +void s2350_device::receiver_sync_reg_w(u8 data) +{ + LOGREG("%s: 0x%02x\n", FUNCNAME, data); + + m_receiver_sync_reg = data; +} + +u8 s2350_device::receiver_sync_search() +{ + set_sync_character_received(false); + m_sync_search_active = true; + + LOGREG("%s: 0x%02x\n", FUNCNAME, m_receiver_sync_reg); + + return m_receiver_sync_reg; +} + +u8 s2350_device::receiver_output_reg_r() +{ + set_received_data_available(false); + + LOGREG("%s: 0x%02x\n", FUNCNAME, m_receiver_output_reg); + + return m_receiver_output_reg; +} + +u8 s2350_device::status_word_r() +{ + u8 status = 0x00; + + status |= m_received_data_available ? 0x01 : 0x00; + status |= m_receiver_overrun ? 0x02 : 0x00; + status |= m_receiver_parity_error ? 0x04 : 0x00; + status |= m_sync_character_received ? 0x08 : 0x00; + status |= m_fill_char_transmitted ? 0x40 : 0x00; + status |= m_transmit_buffer_empty ? 0x80 : 0x00; + + if (!machine().side_effects_disabled()) + { + set_fill_char_transmitted(false); + set_receiver_overrun(false); + set_receiver_parity_error(false); + set_sync_character_received(false); + } + + LOGREG("%s: 0x%02x\n", FUNCNAME, status); + + return status; +} + +void s2350_device::rx_w(int state) +{ + m_serial_rx_line = state; +} + +void s2350_device::receiver_restart() +{ + LOGFUNC("%s\n", FUNCNAME); + + set_received_data_available(false); + set_sync_character_received(false); + set_receiver_overrun(false); + set_receiver_parity_error(false); + + m_sync_search_active = true; + m_serial_rx_state = 0; + m_serial_tx_state = 0; +} + +void s2350_device::receive_byte(u8 data) +{ + if (m_received_data_available) + { + set_receiver_overrun(true); + } + + m_receiver_output_reg = data; + set_received_data_available(true); +} + +void s2350_device::set_transmit_buffer_empty(bool val) +{ + LOGLINE("%s - val: %d\n", FUNCNAME, val); + + m_transmit_buffer_empty = val; + + m_tbmt(val); +} + +void s2350_device::set_fill_char_transmitted(bool val) +{ + LOGLINE("%s - val: %d\n", FUNCNAME, val); + + m_fill_char_transmitted = val; + + m_fct(val); +} + +void s2350_device::set_received_data_available(bool val) +{ + LOGLINE("%s - val: %d\n", FUNCNAME, val); + + m_received_data_available = val; + + m_rda(val); +} + +void s2350_device::set_receiver_overrun(bool val) +{ + LOGLINE("%s - val: %d\n", FUNCNAME, val); + + m_receiver_overrun = val; + + m_ror(val); +} + +void s2350_device::set_receiver_parity_error(bool val) +{ + LOGLINE("%s - val: %d\n", FUNCNAME, val); + + m_receiver_parity_error = val; + + m_rpe(val); +} + +void s2350_device::set_sync_character_received(bool val) +{ + LOGLINE("%s - val: %d\n", FUNCNAME, val); + + m_sync_character_received = val; + + m_scr(val); +} + +void s2350_device::update_receiver_shift() +{ + m_receiver_sync_reg >>= 1; + + m_receiver_shift_reg |= m_serial_rx_line ? 0x80 : 0x00; +} + +void s2350_device::rcp_w() +{ + if (m_in_sync) + { + if (m_serial_rx_state++ == 0) + { + m_receiver_shift_reg = 0; + } + + update_receiver_shift(); + + if (m_serial_rx_state == 8) + { + receive_byte(m_receiver_shift_reg); + + m_serial_rx_state = 0; + } + } + else if (m_sync_search_active) + { + LOGSYNC("%s - searching for sync\n", FUNCNAME); + + update_receiver_shift(); + + // check for a match + if (m_receiver_sync_reg == m_receiver_shift_reg) + { + LOGSYNC("%s - sync found\n", FUNCNAME); + + m_serial_rx_line = 0; + m_in_sync = true; + } + } + else + { + LOGSYNC("%s - ignoring data\n", FUNCNAME); + } +} + +void s2350_device::tcp_w() +{ + if (m_serial_tx_state == 0) + { + if (m_transmit_buffer_empty) + { + set_fill_char_transmitted(true); + m_transmitter_shift_reg = m_transmitter_fill_reg; + } + else + { + set_transmit_buffer_empty(false); + set_fill_char_transmitted(false); + m_transmitter_shift_reg = m_transmitter_holding_reg; + } + } + + m_tx_cb(BIT(m_transmitter_shift_reg, m_serial_tx_state)); + + m_serial_tx_state = (m_serial_tx_state + 1) & 0x7; +} diff --git a/src/devices/machine/s2350.h b/src/devices/machine/s2350.h new file mode 100644 index 00000000000..8726f1af611 --- /dev/null +++ b/src/devices/machine/s2350.h @@ -0,0 +1,119 @@ +// license:BSD-3-Clause +// copyright-holders:Mark Garlanger +/********************************************************************** + + American Systems Inc. S2350 Universal Synchronous Receiver/Transmitter + +**********************************************************************/ + +#ifndef MAME_MACHINE_S2350_H +#define MAME_MACHINE_S2350_H + +#pragma once + +#include "machine/timer.h" + + +// +// AMI S2350 USRT +// +class s2350_device : public device_t +{ +public: + s2350_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); + + // transmit bits + auto tx_handler() { return m_tx_cb.bind(); } + + // transmit statuses + auto transmit_buffer_empty_cb() { return m_tbmt.bind(); } + auto fill_character_transmitted_cb() { return m_fct.bind(); } + + // receive statuses + auto received_data_available_cb() { return m_rda.bind(); } + auto sync_character_received_cb() { return m_scr.bind(); } + auto receiver_overrun_cb() { return m_ror.bind(); } + auto receiver_parity_error_cb() { return m_rpe.bind(); } + + void rx_w(int state); + + void transmitter_holding_reg_w(uint8_t data); + void transmit_fill_reg_w(uint8_t data); + void receiver_sync_reg_w(uint8_t data); + + u8 receiver_output_reg_r(); + u8 status_word_r(); + u8 receiver_sync_search(); + + void receiver_restart(); + + // transmitter clock + void tcp_w(); + // receiver clock + void rcp_w(); + +protected: + + virtual void device_start() override; + virtual void device_reset() override; + + void update_receiver_shift(); + + void set_transmit_buffer_empty(bool val); + void set_fill_char_transmitted(bool val); + + void set_received_data_available(bool val); + void set_receiver_overrun(bool val); + void set_receiver_parity_error(bool val); + void set_sync_character_received(bool val); + + void receive_byte(uint8_t data); + + u8 m_serial_rx_line; + + // transmit flags + bool m_transmit_buffer_empty; + bool m_fill_char_transmitted; + + // transmit registers + u8 m_transmitter_holding_reg; + u8 m_transmitter_fill_reg; + u8 m_transmitter_shift_reg; + + // transmit state (current bit being sent) + uint8_t m_serial_tx_state; + + // transmit status callbacks + devcb_write_line m_tbmt; // Transmit Buffer Empty + devcb_write_line m_fct; // Fill Character Transmitted + + // transmit data callback + devcb_write_line m_tx_cb; + + // receive flags + bool m_received_data_available; + bool m_receiver_overrun; + bool m_receiver_parity_error; // not currently used + bool m_sync_character_received; + + // receive registers + u8 m_receiver_output_reg; + u8 m_receiver_sync_reg; + u8 m_receiver_shift_reg; + + // receiver state + u8 m_serial_rx_state; // current bit being received + bool m_sync_search_active; + bool m_in_sync; + + // receiver status callbacks + devcb_write_line m_rda; // Received Data Available + devcb_write_line m_scr; // Sync Character Received + devcb_write_line m_ror; // Receiver Overrun + devcb_write_line m_rpe; // Receiver Parity Error +}; + + +DECLARE_DEVICE_TYPE(S2350, s2350_device) + +#endif // MAME_MACHINE_S2350_H -- cgit v1.2.3