diff --git a/scripts/src/bus.lua b/scripts/src/bus.lua index b1d38707d32..f0349738813 100644 --- a/scripts/src/bus.lua +++ b/scripts/src/bus.lua @@ -2435,6 +2435,8 @@ if (BUSES["A2BUS"]~=null) then MAME_DIR .. "src/devices/bus/a2bus/a2sam.h", MAME_DIR .. "src/devices/bus/a2bus/a2scsi.cpp", MAME_DIR .. "src/devices/bus/a2bus/a2scsi.h", + MAME_DIR .. "src/devices/bus/a2bus/a2sd.cpp", + MAME_DIR .. "src/devices/bus/a2bus/a2sd.h", MAME_DIR .. "src/devices/bus/a2bus/a2softcard.cpp", MAME_DIR .. "src/devices/bus/a2bus/a2softcard.h", MAME_DIR .. "src/devices/bus/a2bus/a2ssc.cpp", @@ -4365,7 +4367,7 @@ if (BUSES["CBUS"]~=null) then MAME_DIR .. "src/devices/bus/cbus/pc9801_26.cpp", MAME_DIR .. "src/devices/bus/cbus/pc9801_26.h", MAME_DIR .. "src/devices/bus/cbus/pc9801_55.cpp", - MAME_DIR .. "src/devices/bus/cbus/pc9801_55.h", + MAME_DIR .. "src/devices/bus/cbus/pc9801_55.h", MAME_DIR .. "src/devices/bus/cbus/pc9801_86.cpp", MAME_DIR .. "src/devices/bus/cbus/pc9801_86.h", MAME_DIR .. "src/devices/bus/cbus/pc9801_118.cpp", diff --git a/scripts/src/machine.lua b/scripts/src/machine.lua index 3bfdace0099..30f5c86408f 100644 --- a/scripts/src/machine.lua +++ b/scripts/src/machine.lua @@ -4183,6 +4183,17 @@ if (MACHINES["SMARTMEDIA"]~=null) then } end +--------------------------------------------------- +-- +--@src/devices/machine/spi_sdcard.h,MACHINES["SPISDCARD"] = true +--------------------------------------------------- +if (MACHINES["SPISDCARD"]~=null) then + files { + MAME_DIR .. "src/devices/machine/spi_sdcard.cpp", + MAME_DIR .. "src/devices/machine/spi_sdcard.h", + } +end + --------------------------------------------------- -- --@src/devices/machine/appldriv.h,MACHINES["APPLE_DRIVE"] = true diff --git a/scripts/target/mame/arcade.lua b/scripts/target/mame/arcade.lua index dfcd352a012..7ff86036ccb 100644 --- a/scripts/target/mame/arcade.lua +++ b/scripts/target/mame/arcade.lua @@ -651,6 +651,7 @@ MACHINES["SMC91C9X"] = true MACHINES["SEGA_SCU"] = true MACHINES["SMPC"] = true --MACHINES["SPG2XX"] = true +--MACHINES["SPISDCARD"] = true MACHINES["STVCD"] = true --MACHINES["SUN4C_MMU"] = true MACHINES["SWTPC8212"] = true diff --git a/scripts/target/mame/mess.lua b/scripts/target/mame/mess.lua index cf7911fc03e..bc09c366f15 100644 --- a/scripts/target/mame/mess.lua +++ b/scripts/target/mame/mess.lua @@ -692,6 +692,7 @@ MACHINES["SEGA_SCU"] = true MACHINES["SMPC"] = true MACHINES["SPG2XX"] = true MACHINES["SPG290"] = true +MACHINES["SPISDCARD"] = true MACHINES["STVCD"] = true MACHINES["SUN4C_MMU"] = true MACHINES["SWTPC8212"] = true diff --git a/src/devices/bus/a2bus/a2sd.cpp b/src/devices/bus/a2bus/a2sd.cpp new file mode 100644 index 00000000000..c5c9937caaf --- /dev/null +++ b/src/devices/bus/a2bus/a2sd.cpp @@ -0,0 +1,280 @@ +// license:BSD-3-Clause +// copyright-holders:R. Belmont +/********************************************************************* + + a2sd.cpp + + Implementation of the AppleIISD card by Florian Reitz + https://github.com/freitz85/AppleIISd + + AppleIISD has a Xilinx FPGA which implements a minimally hardware + assisted SPI interface, and the SD card is thus driven in SPI + mode rather than SD. + + The SPI controller is fixed to SPI Mode 3 only. + (shift on falling CLK edges, shift-then-latch). + + Firmware is contained in an Atmel 28C64B parallel EEPROM, which + has a Flash-style command set. + +*********************************************************************/ + +#include "emu.h" +#include "a2sd.h" + +#define LOG_GENERAL (1U << 0) +#define LOG_SPI (1U << 1) + +//#define VERBOSE (LOG_COMMAND) +#define LOG_OUTPUT_FUNC osd_printf_info + +#include "logmacro.h" + +/*************************************************************************** + PARAMETERS +***************************************************************************/ + +static constexpr u8 C0N1_ECE = 0x04; // external clock: toggles between 500 kHz internal clock and 1/2 of the 7M A2 bus clock +static constexpr u8 C0N1_FRX = 0x10; // fast recieve: when enabled, both reads and writes of the SPI data register start a shift cycle +[[unused]] static constexpr u8 C0N1_BSY = 0x20; +static constexpr u8 C0N1_TC = 0x80; // SPI transfer complete + +static constexpr u8 C0N3_CD = 0x40; // card detect +static constexpr u8 C0N3_BIT_SS = 7; + +//************************************************************************** +// GLOBAL VARIABLES +//************************************************************************** + +DEFINE_DEVICE_TYPE(A2BUS_A2SD, a2bus_a2sd_device, "a2sd", "Apple II SD Card") + +ROM_START( a2sd ) + ROM_REGION(0x2000, "flash", ROMREGION_ERASE00) + ROM_LOAD( "appleiisd.bin", 0x000000, 0x000800, CRC(e82eea8a) SHA1(7e0acef01e622eeed6f8e87893d07c701bbef016) ) +ROM_END + +/*************************************************************************** + FUNCTION PROTOTYPES +***************************************************************************/ + +//------------------------------------------------- +// device_add_mconfig - add device configuration +//------------------------------------------------- +void a2bus_a2sd_device::device_add_mconfig(machine_config &config) +{ + AT28C64B(config, m_flash, 0); + + SPI_SDCARD(config, m_sdcard, 0); + m_sdcard->spi_miso_callback().set(FUNC(a2bus_a2sd_device::spi_miso_w)); +} + +//------------------------------------------------- +// rom_region - device-specific ROM region +//------------------------------------------------- + +const tiny_rom_entry *a2bus_a2sd_device::device_rom_region() const +{ + return ROM_NAME( a2sd ); +} + +//************************************************************************** +// LIVE DEVICE +//************************************************************************** + +a2bus_a2sd_device::a2bus_a2sd_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) : + device_t(mconfig, type, tag, owner, clock), + device_a2bus_card_interface(mconfig, *this), + m_flash(*this, "flash"), + m_sdcard(*this, "sdcard"), + m_datain(0), m_in_latch(0), m_out_latch(0), m_c0n1(0), m_c0n3(0x80), m_in_bit(0), m_shift_count(0) +{ +} + +a2bus_a2sd_device::a2bus_a2sd_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + a2bus_a2sd_device(mconfig, A2BUS_A2SD, tag, owner, clock) +{ +} + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void a2bus_a2sd_device::device_start() +{ + m_shift_timer = timer_alloc(0); + + save_item(NAME(m_datain)); + save_item(NAME(m_in_latch)); + save_item(NAME(m_out_latch)); + save_item(NAME(m_c0n1)); + save_item(NAME(m_c0n3)); + save_item(NAME(m_in_bit)); + save_item(NAME(m_shift_count)); +} + +void a2bus_a2sd_device::device_reset() +{ + m_shift_timer->adjust(attotime::never); + m_shift_count = 0; + m_sdcard->spi_clock_w(CLEAR_LINE); +} + +void a2bus_a2sd_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) +{ + LOGMASKED(LOG_SPI, ">>>>>>> SHIFT %d (%c)\n", m_shift_count, (m_shift_count & 1) ? 'L' : 'S'); + if (!(m_shift_count & 1)) + { + if (m_shift_count < 16) + { + m_out_latch <<= 1; + } + m_in_latch <<= 1; + m_sdcard->spi_mosi_w(BIT(m_out_latch, 7)); + m_sdcard->spi_clock_w(CLEAR_LINE); + } + else + { + m_in_latch &= ~0x01; + m_in_latch |= m_in_bit; + m_sdcard->spi_clock_w(ASSERT_LINE); + + if (m_shift_count == 1) + { + m_datain = m_in_latch; + LOGMASKED(LOG_SPI, "SPI: got %02x (in latch %02x)\n", m_datain, m_in_latch); + } + } + + m_shift_count--; + if (m_shift_count == 0) + { + m_shift_timer->adjust(attotime::never); + m_c0n1 |= C0N1_TC; // set TC + } +} + +/*------------------------------------------------- + read_c0nx - called for reads from this card's c0nx space +-------------------------------------------------*/ + +u8 a2bus_a2sd_device::read_c0nx(u8 offset) +{ + switch (offset) + { + case 0: + m_c0n1 &= ~C0N1_TC; // clear TC + // if FRX is set, both reads and writes trigger a shift cycle + if (m_c0n1 & C0N1_FRX) + { + m_c0n1 &= ~C0N1_TC; // clear TC + m_shift_count = 16; + m_out_latch = 0xff; + + if (m_c0n1 & C0N1_ECE) + { + m_shift_timer->adjust(attotime::from_hz(14.318181_MHz_XTAL / 4), 0, attotime::from_hz(14.318181_MHz_XTAL / 4)); + } + else + { + m_shift_timer->adjust(attotime::from_hz(500_kHz_XTAL), 0, attotime::from_hz(500_kHz_XTAL)); + } + } + return m_datain; + + case 1: + return m_c0n1; + + case 2: + return 0; + + case 3: + m_c0n3 &= ~C0N3_CD; + m_c0n3 |= m_sdcard->get_card_present() ? 0 : C0N3_CD; // bit is set if no card is present + return m_c0n3; + } + return 0xff; +} + + +/*------------------------------------------------- + write_c0nx - called for writes to this card's c0nx space +-------------------------------------------------*/ + +void a2bus_a2sd_device::write_c0nx(u8 offset, u8 data) +{ + switch (offset) + { + case 0: + if (m_shift_count) + { + return; + } + LOGMASKED(LOG_SPI, "SPI sending %02x\n", data); + m_out_latch = data; + m_sdcard->spi_mosi_w(BIT(m_out_latch, 7)); + m_c0n1 &= ~C0N1_TC; // clear TC + m_shift_count = 16; + // if ECE is set, clock is 3.58 MHz from the A2 bus, otherwise internally generated 500 kHz + if (m_c0n1 & C0N1_ECE) + { + m_shift_timer->adjust(attotime::from_hz(14.318181_MHz_XTAL / 4), 0, attotime::from_hz(14.318181_MHz_XTAL/4)); + } + else + { + m_shift_timer->adjust(attotime::from_hz(500_kHz_XTAL), 0, attotime::from_hz(500_kHz_XTAL)); + } + break; + + case 1: + m_c0n1 &= 0xea; + m_c0n1 |= (data & 0x15); + break; + + case 2: + break; + + case 3: + m_c0n3 &= 0x9f; + m_c0n3 |= (data & 0x91); + + m_sdcard->spi_ss_w(BIT(data, C0N3_BIT_SS)); + LOGMASKED(LOG_GENERAL, "/SS is %x\n", BIT(data, C0N3_BIT_SS)); + break; + + default: + logerror("a2sd: write %02x to c0n%x (%s)\n", data, offset, machine().describe_context().c_str()); + break; + } +} + +/*------------------------------------------------- + read_cnxx - called for reads from this card's cnxx space +-------------------------------------------------*/ + +u8 a2bus_a2sd_device::read_cnxx(u8 offset) +{ + // slot image at 0 + return m_flash->read(offset); +} + +void a2bus_a2sd_device::write_cnxx(u8 offset, u8 data) +{ + m_flash->write(offset, data); +} + +/*------------------------------------------------- + read_c800 - called for reads from this card's c800 space +-------------------------------------------------*/ + +u8 a2bus_a2sd_device::read_c800(u16 offset) +{ + return m_flash->read(offset + 0x100); +} + +/*------------------------------------------------- + write_c800 - called for writes to this card's c800 space +-------------------------------------------------*/ +void a2bus_a2sd_device::write_c800(u16 offset, u8 data) +{ + m_flash->write(offset + 0x100, data); +} diff --git a/src/devices/bus/a2bus/a2sd.h b/src/devices/bus/a2bus/a2sd.h new file mode 100644 index 00000000000..c4d8b4c8f02 --- /dev/null +++ b/src/devices/bus/a2bus/a2sd.h @@ -0,0 +1,67 @@ +// license:BSD-3-Clause +// copyright-holders:R. Belmont +/********************************************************************* + + a2sd.h + + Implementation of the AppleIISD card + +*********************************************************************/ + +#ifndef MAME_BUS_A2BUS_A2SD_H +#define MAME_BUS_A2BUS_A2SD_H + +#pragma once + +#include "a2bus.h" +#include "machine/at28c64b.h" +#include "machine/spi_sdcard.h" + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + +class a2bus_a2sd_device: + public device_t, + public device_a2bus_card_interface +{ +public: + // construction/destruction + a2bus_a2sd_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + +protected: + a2bus_a2sd_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); + + virtual void device_start() override; + virtual void device_reset() override; + virtual void device_add_mconfig(machine_config &config) override; + virtual const tiny_rom_entry *device_rom_region() const override; + virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override; + + // overrides of standard a2bus slot functions + virtual u8 read_c0nx(u8 offset) override; + virtual void write_c0nx(u8 offset, u8 data) override; + virtual u8 read_cnxx(u8 offset) override; + virtual void write_cnxx(u8 offset, u8 data) override; + virtual u8 read_c800(uint16_t offset) override; + virtual void write_c800(uint16_t offset, u8 data) override; + + // SPI 4-wire interface + WRITE_LINE_MEMBER(spi_miso_w) { m_in_bit = state; } + +private: + required_device m_flash; + required_device m_sdcard; + + u8 m_datain, m_in_latch, m_out_latch; + u8 m_c0n1, m_c0n3; + int m_in_bit; + + int m_shift_count; + emu_timer *m_shift_timer; +}; + +// device type definition +DECLARE_DEVICE_TYPE(A2BUS_A2SD, a2bus_a2sd_device) + +#endif // MAME_BUS_A2BUS_A2SD_H diff --git a/src/devices/machine/spi_sdcard.cpp b/src/devices/machine/spi_sdcard.cpp new file mode 100644 index 00000000000..0f51026e852 --- /dev/null +++ b/src/devices/machine/spi_sdcard.cpp @@ -0,0 +1,273 @@ +// license:BSD-3-Clause +// copyright-holders:R. Belmont +/* + SD Card emulation, SPI interface only currently + Emulation by R. Belmont + + This emulates an SDHC card, which means the block size is fixed at 512 bytes and makes things simpler. + Adapting the code to also handle SD version 2 non-HC cards would be relatively straightforward as well; + the block size defaults to 1 byte in that case but can be overridden with CMD16. + + Adding the native 4-bit-wide SD interface is also possible + + Multiple block read/write commands are not supported but would be straightforward to add. + + Refrences: + https://www.sdcard.org/downloads/pls/ (Physical Layer Simplified Specification) + http://www.dejazzer.com/ee379/lecture_notes/lec12_sd_card.pdf + https://embdev.net/attachment/39390/TOSHIBA_SD_Card_Specification.pdf + http://elm-chan.org/docs/mmc/mmc_e.html +*/ + +#include "emu.h" +#include "spi_sdcard.h" +#include "imagedev/harddriv.h" + +#define LOG_GENERAL (1U << 0) +#define LOG_COMMAND (1U << 1) +#define LOG_SPI (1U << 2) + +//#define VERBOSE (LOG_COMMAND) +#define LOG_OUTPUT_FUNC osd_printf_info + +#include "logmacro.h" + +static constexpr u8 DATA_RESPONSE_OK = 0x05; +static constexpr u8 DATA_RESPONSE_IO_ERROR = 0x0d; + +DEFINE_DEVICE_TYPE(SPI_SDCARD, spi_sdcard_device, "spi_sdcard", "SD Card (SPI Interface)") + +spi_sdcard_device::spi_sdcard_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) : + device_t(mconfig, type, tag, owner, clock), + write_miso(*this), + m_image(*this, "image"), + m_harddisk(nullptr), + m_in_latch(0), m_out_latch(0), m_cmd_ptr(0), m_state(0), m_out_ptr(0), m_out_count(0), m_ss(0), m_in_bit(0), + m_cur_bit(0), m_write_ptr(0), m_bACMD(false) +{ +} + +spi_sdcard_device::spi_sdcard_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + spi_sdcard_device(mconfig, SPI_SDCARD, tag, owner, clock) +{ +} + +void spi_sdcard_device::device_start() +{ + write_miso.resolve_safe(); + save_item(NAME(m_in_latch)); + save_item(NAME(m_out_latch)); + save_item(NAME(m_cmd_ptr)); + save_item(NAME(m_state)); + save_item(NAME(m_out_ptr)); + save_item(NAME(m_out_count)); + save_item(NAME(m_ss)); + save_item(NAME(m_in_bit)); + save_item(NAME(m_cur_bit)); + save_item(NAME(m_write_ptr)); + save_item(NAME(m_cmd)); + save_item(NAME(m_data)); + save_item(NAME(m_bACMD)); +} + +void spi_sdcard_device::device_reset() +{ + m_harddisk = m_image->get_hard_disk_file(); +} + +void spi_sdcard_device::device_add_mconfig(machine_config &config) +{ + HARDDISK(config, m_image).set_interface("spi_sdcard"); +} + +void spi_sdcard_device::send_data(int count) +{ + m_out_ptr = 0; + m_out_count = count; +} + +void spi_sdcard_device::spi_clock_w(int state) +{ + // only respond if selected + if (m_ss) + { + // We implmement SPI Mode 3 signalling, in which we latch the data on + // rising clock edges, and shift the data on falling clock edges. + // See http://www.dejazzer.com/ee379/lecture_notes/lec12_sd_card.pdf for details + // on the 4 SPI signalling modes. SD Cards can work in ether Mode 0 or Mode 3, + // both of which shift on the falling edge and latch on the rising edge but + // have opposite CLK polarity. + + if (state) + { + m_in_latch &= ~0x01; + m_in_latch |= m_in_bit; + LOGMASKED(LOG_SPI, "\tsdcard: L %02x (%d) (out %02x)\n", m_in_latch, m_cur_bit, m_out_latch); + m_cur_bit++; + if (m_cur_bit == 8) + { + LOGMASKED(LOG_SPI, "SDCARD: got %02x\n", m_in_latch); + + switch (m_state) + { + case SD_STATE_IDLE: + for (int i = 0; i < 5; i++) + { + m_cmd[i] = m_cmd[i + 1]; + } + m_cmd[5] = m_in_latch; + + if ((((m_cmd[0] & 0xc0) == 0x40) && (m_cmd[5] & 1)) && (m_out_count == 0)) + { + do_command(); + } + break; + + case SD_STATE_WRITE_WAITFE: + if (m_in_latch == 0xfe) + { + m_state = SD_STATE_WRITE_DATA; + m_out_latch = 0xff; + m_write_ptr = 0; + } + break; + + case SD_STATE_WRITE_DATA: + m_data[m_write_ptr++] = m_in_latch; + if (m_write_ptr == 514) + { + u32 blk = (m_cmd[1] << 24) | (m_cmd[2] << 16) | (m_cmd[3] << 8) | m_cmd[4]; + LOGMASKED(LOG_GENERAL, "writing LBA %x, data %02x %02x %02x %02x\n", blk, m_data[0], m_data[1], m_data[2], m_data[3]); + if (hard_disk_write(m_harddisk, blk, &m_data[0])) + { + m_data[0] = DATA_RESPONSE_OK; + } + else + { + m_data[0] = DATA_RESPONSE_IO_ERROR; + } + m_data[1] = 0x01; + + m_state = SD_STATE_IDLE; + send_data(2); + } + break; + } + } + } + else + { + m_in_latch <<= 1; + m_out_latch <<= 1; + LOGMASKED(LOG_SPI, "\tsdcard: S %02x %02x (%d)\n", m_in_latch, m_out_latch, m_cur_bit); + if (m_cur_bit == 8) + { + m_cur_bit = 0; + } + + if (m_cur_bit == 0) + { + if (m_out_count > 0) + { + m_out_latch = m_data[m_out_ptr++]; + LOGMASKED(LOG_SPI, "SDCARD: latching %02x (start of shift)\n", m_out_latch); + m_out_count--; + } + } + + write_miso(BIT(m_out_latch, 7) ? ASSERT_LINE : CLEAR_LINE); + } + } +} + +void spi_sdcard_device::do_command() +{ + LOGMASKED(LOG_COMMAND, "SDCARD: cmd %02d %02x %02x %02x %02x %02x\n", m_cmd[0] & 0x3f, m_cmd[1], m_cmd[2], m_cmd[3], m_cmd[4], m_cmd[5]); + switch (m_cmd[0] & 0x3f) + { + case 0: // CMD0 - GO_IDLE_STATE + if (m_harddisk) + { + m_data[0] = 0x01; + } + else + { + m_data[0] = 0x00; + } + send_data(1); + break; + + case 8: // CMD8 - SEND_IF_COND (SD v2 only) + m_data[0] = 0x01; + m_data[1] = 0; + m_data[2] = 0; + m_data[3] = 0; + m_data[4] = 0xaa; + send_data(5); + break; + + case 17: // CMD17 - READ_SINGLE_BLOCK + if (m_harddisk) + { + m_data[0] = 0x00; // initial R1 response + // data token occurs some time after the R1 response. A2SD expects at least 1 + // byte of space between R1 and the data packet. + m_data[2] = 0xfe; // data token + u32 blk = (m_cmd[1] << 24) | (m_cmd[2] << 16) | (m_cmd[3] << 8) | m_cmd[4]; + LOGMASKED(LOG_GENERAL, "reading LBA %x\n", blk); + hard_disk_read(m_harddisk, blk, &m_data[3]); + send_data(3 + 512 + 2); + } + else + { + m_data[0] = 0xff; // show an error + send_data(1); + } + break; + + case 24: // CMD24 - WRITE_BLOCK + m_data[0] = 0; + send_data(1); + m_state = SD_STATE_WRITE_WAITFE; + break; + + case 41: + if (m_bACMD) // ACMD41 - SD_SEND_OP_COND + { + m_data[0] = 0; + } + else // CMD41 - illegal + { + m_data[0] = 0xff; + } + send_data(1); + break; + + case 55: // CMD55 - APP_CMD + m_data[0] = 0x01; + send_data(1); + break; + + case 58: // CMD58 - READ_OCR + m_data[0] = 0; + m_data[1] = 0x40; // indicate SDHC support + m_data[2] = 0; + m_data[3] = 0; + m_data[4] = 0; + send_data(5); + break; + + default: + break; + } + + // if this is command 55, that's a prefix indicating the next command is an "app command" or "ACMD" + if ((m_cmd[0] & 0x3f) == 55) + { + m_bACMD = true; + } + else + { + m_bACMD = false; + } +} diff --git a/src/devices/machine/spi_sdcard.h b/src/devices/machine/spi_sdcard.h new file mode 100644 index 00000000000..4bd79e5aa30 --- /dev/null +++ b/src/devices/machine/spi_sdcard.h @@ -0,0 +1,55 @@ +// license:BSD-3-Clause +// copyright-holders:R. Belmont +#ifndef MAME_MACHINE_SPI_SDCARD_H +#define MAME_MACHINE_SPI_SDCARD_H + +#pragma once + +#include "imagedev/harddriv.h" + +class spi_sdcard_device : public device_t +{ +public: + spi_sdcard_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + // SPI 4-wire interface + auto spi_miso_callback() { return write_miso.bind(); } + void spi_clock_w(int state); + void spi_ss_w(int state) { m_ss = state; } + void spi_mosi_w(int state) { m_in_bit = state; } + + bool get_card_present() { return !(m_harddisk == nullptr); } + + devcb_write_line write_miso; + +protected: + spi_sdcard_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); + + virtual void device_start() override; + virtual void device_reset() override; + virtual void device_add_mconfig(machine_config &config) override; + + required_device m_image; + +private: + enum + { + SD_STATE_IDLE = 0, + SD_STATE_WRITE_WAITFE, + SD_STATE_WRITE_DATA + }; + + void send_data(int count); + void do_command(); + + u8 m_data[520], m_cmd[6]; + hard_disk_file *m_harddisk; + + u8 m_in_latch, m_out_latch; + int m_cmd_ptr, m_state, m_out_ptr, m_out_count, m_ss, m_in_bit, m_cur_bit, m_write_ptr; + bool m_bACMD; +}; + +DECLARE_DEVICE_TYPE(SPI_SDCARD, spi_sdcard_device) + +#endif // MAME_MACHINE_SPI_SDCARD_H diff --git a/src/mame/drivers/apple2e.cpp b/src/mame/drivers/apple2e.cpp index 4a0b7119b64..ed169af47b9 100644 --- a/src/mame/drivers/apple2e.cpp +++ b/src/mame/drivers/apple2e.cpp @@ -159,6 +159,7 @@ MIG RAM page 2 $CE02 is the speaker/slot bitfield and $CE03 is the paddle/accele #include "bus/a2bus/a2pic.h" #include "bus/a2bus/a2sam.h" #include "bus/a2bus/a2scsi.h" +#include "bus/a2bus/a2sd.h" #include "bus/a2bus/a2softcard.h" #include "bus/a2bus/a2ssc.h" #include "bus/a2bus/a2swyft.h" @@ -1904,19 +1905,19 @@ void apple2e_state::do_io(int offset, bool is_iic) } // 558 monostable one-shot timers; a running timer cannot be restarted - if (machine().time().as_double() >= m_joystick_x1_time) + if (machine().time().as_double() >= m_joystick_x1_time) { m_joystick_x1_time = machine().time().as_double() + m_x_calibration * m_gameio->pdl0_r(); } - if (machine().time().as_double() >= m_joystick_y1_time) + if (machine().time().as_double() >= m_joystick_y1_time) { m_joystick_y1_time = machine().time().as_double() + m_y_calibration * m_gameio->pdl1_r(); } - if (machine().time().as_double() >= m_joystick_x2_time) + if (machine().time().as_double() >= m_joystick_x2_time) { m_joystick_x2_time = machine().time().as_double() + m_x_calibration * m_gameio->pdl2_r(); } - if (machine().time().as_double() >= m_joystick_y2_time) + if (machine().time().as_double() >= m_joystick_y2_time) { m_joystick_y2_time = machine().time().as_double() + m_y_calibration * m_gameio->pdl3_r(); } @@ -4719,6 +4720,7 @@ static void apple2_cards(device_slot_interface &device) device.option_add("lancegs", A2BUS_LANCEGS); /* ///SHH SYSTEME LANceGS Card */ device.option_add("q68", A2BUS_Q68); /* Stellation Q68 68000 card */ device.option_add("q68plus", A2BUS_Q68PLUS); /* Stellation Q68 Plus 68000 card */ + device.option_add("a2sd", A2BUS_A2SD); /* Florian Reitz AppleIISD */ } static void apple2eaux_cards(device_slot_interface &device)