From b788307114fa79910520dcccedcea7885fe2b68c Mon Sep 17 00:00:00 2001 From: Nigel Barnes Date: Sat, 4 Jun 2022 20:10:20 +0100 Subject: bus/electron: Added the ElkSD64 and ElkSD128 Electron SD interfaces. --- scripts/src/bus.lua | 4 + src/devices/bus/electron/elksd128.cpp | 318 ++++++++++++++++++++++++++++++++++ src/devices/bus/electron/elksd128.h | 69 ++++++++ src/devices/bus/electron/elksd64.cpp | 161 +++++++++++++++++ src/devices/bus/electron/elksd64.h | 55 ++++++ src/devices/bus/electron/exp.cpp | 4 + 6 files changed, 611 insertions(+) create mode 100644 src/devices/bus/electron/elksd128.cpp create mode 100644 src/devices/bus/electron/elksd128.h create mode 100644 src/devices/bus/electron/elksd64.cpp create mode 100644 src/devices/bus/electron/elksd64.h diff --git a/scripts/src/bus.lua b/scripts/src/bus.lua index afc4b22528f..e3a695648fd 100644 --- a/scripts/src/bus.lua +++ b/scripts/src/bus.lua @@ -1196,6 +1196,10 @@ if (BUSES["ELECTRON"]~=null) then files { MAME_DIR .. "src/devices/bus/electron/exp.cpp", MAME_DIR .. "src/devices/bus/electron/exp.h", + MAME_DIR .. "src/devices/bus/electron/elksd64.cpp", + MAME_DIR .. "src/devices/bus/electron/elksd64.h", + MAME_DIR .. "src/devices/bus/electron/elksd128.cpp", + MAME_DIR .. "src/devices/bus/electron/elksd128.h", MAME_DIR .. "src/devices/bus/electron/fbjoy.cpp", MAME_DIR .. "src/devices/bus/electron/fbjoy.h", MAME_DIR .. "src/devices/bus/electron/fbprint.cpp", diff --git a/src/devices/bus/electron/elksd128.cpp b/src/devices/bus/electron/elksd128.cpp new file mode 100644 index 00000000000..302144bb343 --- /dev/null +++ b/src/devices/bus/electron/elksd128.cpp @@ -0,0 +1,318 @@ +// license:BSD-3-Clause +// copyright-holders:Nigel Barnes +/********************************************************************** + + ElkSD128 Electron SD Interface + + SD Card Interface, 128K Memory Expansion & Joystick Adapter + + http://ramtop-retro.uk/elksd128.html + +**********************************************************************/ + + +#include "emu.h" +#include "elksd128.h" + + +//************************************************************************** +// DEVICE DEFINITIONS +//************************************************************************** + +DEFINE_DEVICE_TYPE(ELECTRON_ELKSD128, electron_elksd128_device, "electron_elksd128", "ElkSD128 Electron SD Interface") + + +static INPUT_PORTS_START( elksd128 ) + PORT_START("JOY") + PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP) PORT_8WAY + PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN) PORT_8WAY + PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT) PORT_8WAY + PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT) PORT_8WAY + PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_NAME("Fire") + PORT_BIT(0xe0, IP_ACTIVE_LOW, IPT_UNUSED) +INPUT_PORTS_END + +//------------------------------------------------- +// input_ports - device-specific input ports +//------------------------------------------------- + +ioport_constructor electron_elksd128_device::device_input_ports() const +{ + return INPUT_PORTS_NAME( elksd128 ); +} + + +//------------------------------------------------- +// ROM( elksd128 ) +//------------------------------------------------- + +ROM_START( elksd128 ) + ROM_REGION(0x80000, "flash", 0) + ROM_LOAD("esd12815.rom", 0x0000, 0x80000, CRC(3ecf23ce) SHA1(d552149fec6a1deec2b75c740092bd311d67046f)) +ROM_END + +//------------------------------------------------- +// device_add_mconfig - add device configuration +//------------------------------------------------- + +void electron_elksd128_device::device_add_mconfig(machine_config &config) +{ + SPI_SDCARD(config, m_sdcard, 0); + m_sdcard->spi_miso_callback().set([this](int state) { m_in_bit = state; }); +} + +//------------------------------------------------- +// rom_region - device-specific ROM region +//------------------------------------------------- + +const tiny_rom_entry *electron_elksd128_device::device_rom_region() const +{ + return ROM_NAME( elksd128 ); +} + +//************************************************************************** +// LIVE DEVICE +//************************************************************************** + +//------------------------------------------------- +// electron_elksd128_device - constructor +//------------------------------------------------- + +electron_elksd128_device::electron_elksd128_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : device_t(mconfig, ELECTRON_ELKSD128, tag, owner, clock) + , device_electron_expansion_interface(mconfig, *this) + , m_flash(*this, "flash") + , m_sdcard(*this, "sdcard") + , m_joy(*this, "JOY") + , m_romsel(0) + , m_adc_channel(0) + , m_swr_lock(0) + , m_spi_clock_state(false) + , m_spi_clock_sysclk(false) + , m_spi_clock_cycles(0) +{ +} + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void electron_elksd128_device::device_start() +{ + m_ram = make_unique_clear(0x20000); + + m_spi_clock = timer_alloc(FUNC(electron_elksd128_device::spi_clock), this); + + save_item(NAME(m_romsel)); + save_item(NAME(m_adc_channel)); + save_item(NAME(m_swr_lock)); + save_pointer(NAME(m_ram), 0x20000); + save_item(NAME(m_spi_clock_state)); + save_item(NAME(m_spi_clock_sysclk)); + save_item(NAME(m_spi_clock_cycles)); + save_item(NAME(m_in_bit)); + save_item(NAME(m_in_latch)); + save_item(NAME(m_out_latch)); +} + +//------------------------------------------------- +// device_reset - device-specific startup +//------------------------------------------------- + +void electron_elksd128_device::device_reset() +{ + m_spi_clock->adjust(attotime::never); + m_spi_clock_cycles = 0; + m_spi_clock_state = false; +} + + +//------------------------------------------------- +// expbus_r - expansion data read +//------------------------------------------------- + +uint8_t electron_elksd128_device::expbus_r(offs_t offset) +{ + uint8_t data = 0xff; + + switch (offset >> 12) + { + case 0x8: case 0x9: case 0xa: case 0xb: + switch (m_romsel) + { + case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: + data = m_ram[(m_romsel) << 14 | (offset & 0x3fff)]; + break; + + case 12: + data = m_flash->base()[(m_romsel - 10) << 14 | (offset & 0x3fff)]; + break; + + case 14: case 15: + data = m_flash->base()[(m_romsel - 14) << 14 | (offset & 0x3fff)]; + break; + } + break; + + case 0xf: + switch (offset >> 8) + { + case 0xfc: + switch (offset) + { + case 0xfc70: // Plus 1 analogue/digital converter + switch (m_adc_channel) + { + case 0x04: + if (!BIT(m_joy->read(), 3)) + data = 0x00; + else if (!BIT(m_joy->read(), 2)) + data = 0xff; + else + data = 0x80; + break; + case 0x05: + if (!BIT(m_joy->read(), 1)) + data = 0x00; + else if (!BIT(m_joy->read(), 0)) + data = 0xff; + else + data = 0x80; + break; + case 0x06: + case 0x07: + data = 0x80; + break; + } + break; + + case 0xfc72: // Plus 1 joystick and ADC status + data = 0xaf | (m_joy->read() & 0x10); + break; + + case 0xfc80: // SPI controller data port + data = m_in_latch; + break; + + case 0xfc81: // SPI controller status register + data = m_spi_clock_cycles > 0 ? 0x01 : 0x00; + break; + + case 0xfc83: // Device ID + data = 0x80; // ElkSD128 rev 1.0 + break; + + case 0xfcc0: // First Byte interface + data = m_joy->read() | 0xe0; + break; + + case 0xfcd0: // Slogger interface + data = m_joy->read() | 0xe0; + break; + } + break; + } + } + + return data; +} + + +//------------------------------------------------- +// expbus_w - expansion data write +//------------------------------------------------- + +void electron_elksd128_device::expbus_w(offs_t offset, uint8_t data) +{ + switch (offset >> 12) + { + case 0x8: case 0x9: case 0xa: case 0xb: + switch (m_romsel) + { + case 0: case 1: case 2: case 3: case 4: case 5: + m_ram[(m_romsel) << 14 | (offset & 0x3fff)] = data; + break; + case 6: + if (!BIT(m_swr_lock, 6) || (offset & 0x3fff) > 0x3600) + m_ram[(m_romsel) << 14 | (offset & 0x3fff)] = data; + break; + case 7: + if (BIT(m_swr_lock, 7) || (offset & 0x3fff) > 0x3600) + m_ram[(m_romsel) << 14 | (offset & 0x3fff)] = data; + break; + } + break; + + case 0xf: + switch (offset >> 8) + { + case 0xfc: + switch (offset) + { + case 0xfc70: // Plus 1 analogue/digital converter + m_adc_channel = data; + break; + + case 0xfc80: // SPI controller data port + m_out_latch = data; + m_spi_clock_cycles = 8; + + if (m_spi_clock_sysclk) // TODO: confirm fast/slow clock dividers + m_spi_clock->adjust(attotime::from_hz(16_MHz_XTAL / 2), 0, attotime::from_hz(16_MHz_XTAL / 2)); + else + m_spi_clock->adjust(attotime::from_hz(16_MHz_XTAL / 32), 0, attotime::from_hz(16_MHz_XTAL / 32)); + break; + + case 0xfc81: // SPI controller clock register + m_spi_clock_sysclk = bool(BIT(data, 0)); + break; + + case 0xfc82: // Sideways RAM lock + m_swr_lock = data; + break; + } + break; + + case 0xfe: + if (offset == 0xfe05) + { + m_romsel = data & 0x0f; + } + break; + } + } +} + + +TIMER_CALLBACK_MEMBER(electron_elksd128_device::spi_clock) +{ + if (m_spi_clock_cycles > 0) + { + m_sdcard->spi_ss_w(1); + + if (m_spi_clock_state) + { + m_in_latch <<= 1; + m_in_latch &= ~0x01; + m_in_latch |= m_in_bit; + + m_sdcard->spi_clock_w(1); + + m_spi_clock_cycles--; + } + else + { + m_sdcard->spi_mosi_w(BIT(m_out_latch, 7)); + m_sdcard->spi_clock_w(0); + + m_out_latch <<= 1; + } + + m_spi_clock_state = !m_spi_clock_state; + } + else + { + m_spi_clock_state = false; + m_spi_clock->adjust(attotime::never); + } +} diff --git a/src/devices/bus/electron/elksd128.h b/src/devices/bus/electron/elksd128.h new file mode 100644 index 00000000000..48ff1375ea9 --- /dev/null +++ b/src/devices/bus/electron/elksd128.h @@ -0,0 +1,69 @@ +// license:BSD-3-Clause +// copyright-holders:Nigel Barnes +/********************************************************************** + + ElkSD128 Electron SD Interface + +**********************************************************************/ + + +#ifndef MAME_BUS_ELECTRON_ELKSD128_H +#define MAME_BUS_ELECTRON_ELKSD128_H + +#include "exp.h" +#include "machine/spi_sdcard.h" + + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + +class electron_elksd128_device: + public device_t, + public device_electron_expansion_interface +{ +public: + // construction/destruction + electron_elksd128_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + +protected: + // device-level overrides + virtual void device_start() override; + virtual void device_reset() override; + + // optional information overrides + virtual void device_add_mconfig(machine_config &config) override; + virtual ioport_constructor device_input_ports() const override; + virtual const tiny_rom_entry *device_rom_region() const override; + + virtual uint8_t expbus_r(offs_t offset) override; + virtual void expbus_w(offs_t offset, uint8_t data) override; + +private: + required_memory_region m_flash; + required_device m_sdcard; + required_ioport m_joy; + + uint8_t m_romsel; + uint8_t m_adc_channel; + uint8_t m_swr_lock; + + TIMER_CALLBACK_MEMBER(spi_clock); + + emu_timer *m_spi_clock; + bool m_spi_clock_state; + bool m_spi_clock_sysclk; + int m_spi_clock_cycles; + int m_in_bit; + uint8_t m_in_latch; + uint8_t m_out_latch; + + std::unique_ptr m_ram; +}; + + +// device type definition +DECLARE_DEVICE_TYPE(ELECTRON_ELKSD128, electron_elksd128_device) + + +#endif /* MAME_BUS_ELECTRON_ELKSD128_H */ diff --git a/src/devices/bus/electron/elksd64.cpp b/src/devices/bus/electron/elksd64.cpp new file mode 100644 index 00000000000..c76c9a8c685 --- /dev/null +++ b/src/devices/bus/electron/elksd64.cpp @@ -0,0 +1,161 @@ +// license:BSD-3-Clause +// copyright-holders:Nigel Barnes +/********************************************************************** + + ElkSD64 Electron SD Interface + + SD Card Interface & 64K RAM Expansion + + http://ramtop-retro.uk/elksd64.html + +**********************************************************************/ + + +#include "emu.h" +#include "elksd64.h" + + +//************************************************************************** +// DEVICE DEFINITIONS +//************************************************************************** + +DEFINE_DEVICE_TYPE(ELECTRON_ELKSD64, electron_elksd64_device, "electron_elksd64", "ElkSD64 Electron SD Interface") + + +//------------------------------------------------- +// ROM( elksd64 ) +//------------------------------------------------- + +ROM_START( elksd64 ) + ROM_REGION(0x20000, "flash", ROMREGION_ERASE00) // SST39SF010 + ROM_LOAD("zemmfs.bin", 0x0000, 0x4000, CRC(c3d38702) SHA1(8a1f0615ff93549815f4c8d21e35fb89535941dc)) + ROM_LOAD("ap6rom.rom", 0x4000, 0x4000, CRC(364591eb) SHA1(316a25aeeda0266dae510eea52324b087875740f)) +ROM_END + +//------------------------------------------------- +// device_add_mconfig - add device configuration +//------------------------------------------------- + +void electron_elksd64_device::device_add_mconfig(machine_config &config) +{ + SPI_SDCARD(config, m_sdcard, 0); + m_sdcard->spi_miso_callback().set([this](int state) { m_status = state << 7; }); +} + +//------------------------------------------------- +// rom_region - device-specific ROM region +//------------------------------------------------- + +const tiny_rom_entry *electron_elksd64_device::device_rom_region() const +{ + return ROM_NAME( elksd64 ); +} + +//************************************************************************** +// LIVE DEVICE +//************************************************************************** + +//------------------------------------------------- +// electron_elksd64_device - constructor +//------------------------------------------------- + +electron_elksd64_device::electron_elksd64_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : device_t(mconfig, ELECTRON_ELKSD64, tag, owner, clock) + , device_electron_expansion_interface(mconfig, *this) + , m_flash(*this, "flash") + , m_sdcard(*this, "sdcard") + , m_romsel(0) + , m_status(0) +{ +} + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void electron_elksd64_device::device_start() +{ + m_ram = make_unique_clear(0x8000); + + save_item(NAME(m_romsel)); + save_item(NAME(m_status)); + save_pointer(NAME(m_ram), 0x8000); +} + +//------------------------------------------------- +// expbus_r - expansion data read +//------------------------------------------------- + +uint8_t electron_elksd64_device::expbus_r(offs_t offset) +{ + uint8_t data = 0xff; + + switch (offset >> 12) + { + case 0x8: case 0x9: case 0xa: case 0xb: + switch (m_romsel) + { + case 12: case 13: + data = m_ram[(m_romsel - 12) << 14 | (offset & 0x3fff)]; + break; + + case 14: case 15: + data = m_flash->base()[(m_romsel - 14) << 14 | (offset & 0x3fff)]; + break; + } + break; + + case 0xf: + switch (offset >> 8) + { + case 0xfc: + if (offset == 0xfc72) + { + data = m_status; + } + break; + } + } + + return data; +} + + +//------------------------------------------------- +// expbus_w - expansion data write +//------------------------------------------------- + +void electron_elksd64_device::expbus_w(offs_t offset, uint8_t data) +{ + switch (offset >> 12) + { + case 0x8: case 0x9: case 0xa: case 0xb: + switch (m_romsel) + { + case 12: case 13: + m_ram[(m_romsel - 12) << 14 | (offset & 0x3fff)] = data; + break; + } + break; + + case 0xf: + switch (offset >> 8) + { + case 0xfc: + if (offset == 0xfc71) + { + m_sdcard->spi_ss_w(1); + m_sdcard->spi_mosi_w(BIT(data, 0)); + m_sdcard->spi_clock_w(BIT(data, 1)); + } + break; + + case 0xfe: + if (offset == 0xfe05) + { + m_romsel = data & 0x0f; + } + break; + } + } +} diff --git a/src/devices/bus/electron/elksd64.h b/src/devices/bus/electron/elksd64.h new file mode 100644 index 00000000000..d21b9595fc0 --- /dev/null +++ b/src/devices/bus/electron/elksd64.h @@ -0,0 +1,55 @@ +// license:BSD-3-Clause +// copyright-holders:Nigel Barnes +/********************************************************************** + + ElkSD64 Electron SD Interface + +**********************************************************************/ + + +#ifndef MAME_BUS_ELECTRON_ELKSD64_H +#define MAME_BUS_ELECTRON_ELKSD64_H + +#include "exp.h" +#include "machine/spi_sdcard.h" + + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + +class electron_elksd64_device: + public device_t, + public device_electron_expansion_interface +{ +public: + // construction/destruction + electron_elksd64_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + +protected: + // device-level overrides + virtual void device_start() override; + + // optional information overrides + virtual void device_add_mconfig(machine_config &config) override; + virtual const tiny_rom_entry *device_rom_region() const override; + + virtual uint8_t expbus_r(offs_t offset) override; + virtual void expbus_w(offs_t offset, uint8_t data) override; + +private: + required_memory_region m_flash; + required_device m_sdcard; + + uint8_t m_romsel; + uint8_t m_status; + + std::unique_ptr m_ram; +}; + + +// device type definition +DECLARE_DEVICE_TYPE(ELECTRON_ELKSD64, electron_elksd64_device) + + +#endif /* MAME_BUS_ELECTRON_ELKSD64_H */ diff --git a/src/devices/bus/electron/exp.cpp b/src/devices/bus/electron/exp.cpp index 304306b09a0..6198b1abd0f 100644 --- a/src/devices/bus/electron/exp.cpp +++ b/src/devices/bus/electron/exp.cpp @@ -99,6 +99,8 @@ void electron_expansion_slot_device::expbus_w(offs_t offset, uint8_t data) // slot devices +#include "elksd64.h" +#include "elksd128.h" #include "fbjoy.h" #include "fbprint.h" #include "mc68k.h" @@ -119,6 +121,8 @@ void electron_expansion_devices(device_slot_interface &device) { device.option_add("ap1", ELECTRON_AP1); device.option_add("ap6", ELECTRON_AP6); + device.option_add("elksd64", ELECTRON_ELKSD64); + device.option_add("elksd128", ELECTRON_ELKSD128); device.option_add("fbjoy", ELECTRON_FBJOY); device.option_add("fbprint", ELECTRON_FBPRINT); device.option_add("mc68k", ELECTRON_MC68K); -- cgit v1.2.3