mirror of
https://github.com/mamedev/mame.git
synced 2024-11-16 07:48:32 +01:00
vtech/sdloader: Add support for SPI SD card
This commit is contained in:
parent
0fb4ca2c8b
commit
6b96a5d24b
2 changed files with 122 additions and 6 deletions
|
@ -6,15 +6,26 @@
|
|||
|
||||
Notes:
|
||||
- Also works for VZ200
|
||||
- The loader can't format the SD card, so you need to do that yourself
|
||||
Instructions for Linux:
|
||||
* dd if=/dev/zero of=vz300.img count=2048 bs=1M
|
||||
* mkfs.vfat vz300.img
|
||||
* mount image and copy .vz files to it
|
||||
* chdman createhd -o vz300.chd -i vz300.img -c none
|
||||
|
||||
TODO:
|
||||
- No SD card emulation, so only the memory expansion part works
|
||||
- SPI clock needed too fast
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "sdloader.h"
|
||||
|
||||
#define LOG_GENERAL (1U << 0)
|
||||
#define LOG_SPI (1U << 1)
|
||||
#define VERBOSE (LOG_GENERAL)
|
||||
#include "logmacro.h"
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// DEVICE DEFINITIONS
|
||||
|
@ -68,6 +79,18 @@ const tiny_rom_entry *vtech_sdloader_device::device_rom_region() const
|
|||
return ROM_NAME( sdloader );
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_add_mconfig - add device configuration
|
||||
//-------------------------------------------------
|
||||
|
||||
void vtech_sdloader_device::device_add_mconfig(machine_config &config)
|
||||
{
|
||||
vtech_memexp_device::device_add_mconfig(config);
|
||||
|
||||
SPI_SDCARD(config, m_sdcard, 0);
|
||||
m_sdcard->spi_miso_callback().set(FUNC(vtech_sdloader_device::spi_miso_w));
|
||||
}
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// LIVE DEVICE
|
||||
|
@ -79,9 +102,12 @@ const tiny_rom_entry *vtech_sdloader_device::device_rom_region() const
|
|||
|
||||
vtech_sdloader_device::vtech_sdloader_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
|
||||
vtech_memexp_device(mconfig, VTECH_SDLOADER, tag, owner, clock),
|
||||
m_sdcard(*this, "sdcard"),
|
||||
m_dosbank(*this, "dosbank"),
|
||||
m_dosview(*this, "dosview"),
|
||||
m_expbank(*this, "expbank"),
|
||||
m_spi_clock_state(false),
|
||||
m_spi_clock_cycles(0),
|
||||
m_vz300_mode(false)
|
||||
{
|
||||
}
|
||||
|
@ -103,7 +129,16 @@ void vtech_sdloader_device::device_start()
|
|||
m_expbank->configure_entry(0, m_ram.get() + 0x10000);
|
||||
m_expbank->configure_entry(1, m_ram.get() + 0x18000);
|
||||
|
||||
// allocate timer for sdcard
|
||||
m_spi_clock = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(vtech_sdloader_device::spi_clock), this));
|
||||
|
||||
// register for savestates
|
||||
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));
|
||||
save_item(NAME(m_vz300_mode));
|
||||
save_pointer(NAME(m_ram), 0x20000);
|
||||
}
|
||||
|
@ -119,6 +154,10 @@ void vtech_sdloader_device::device_reset()
|
|||
|
||||
// rom enabled
|
||||
m_dosview.select(0);
|
||||
|
||||
m_spi_clock->adjust(attotime::never);
|
||||
m_spi_clock_cycles = 0;
|
||||
m_spi_clock_state = false;
|
||||
}
|
||||
|
||||
|
||||
|
@ -126,6 +165,48 @@ void vtech_sdloader_device::device_reset()
|
|||
// IMPLEMENTATION
|
||||
//**************************************************************************
|
||||
|
||||
TIMER_CALLBACK_MEMBER(vtech_sdloader_device::spi_clock)
|
||||
{
|
||||
if (m_spi_clock_cycles > 0)
|
||||
{
|
||||
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
|
||||
{
|
||||
if (m_spi_clock_cycles == 8)
|
||||
LOGMASKED(LOG_SPI, "SPI transfer start\n");
|
||||
|
||||
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
|
||||
{
|
||||
LOGMASKED(LOG_SPI, "SPI transfer done\n");
|
||||
m_spi_clock_state = false;
|
||||
m_spi_clock->adjust(attotime::never);
|
||||
}
|
||||
}
|
||||
|
||||
void vtech_sdloader_device::spi_miso_w(int state)
|
||||
{
|
||||
LOGMASKED(LOG_SPI, "spi_miso_w: %d\n", state);
|
||||
|
||||
m_in_bit = state;
|
||||
}
|
||||
|
||||
void vtech_sdloader_device::mapper_w(uint8_t data)
|
||||
{
|
||||
// 7654---- not used
|
||||
|
@ -141,23 +222,44 @@ void vtech_sdloader_device::mapper_w(uint8_t data)
|
|||
|
||||
void vtech_sdloader_device::sdcfg_w(uint8_t data)
|
||||
{
|
||||
logerror("sdcfg_w: %02x\n", data);
|
||||
// 765432-- not used
|
||||
// ------1- sd card cs
|
||||
// -------0 clock speed
|
||||
|
||||
LOGMASKED(LOG_SPI, "sdcfg_w: %02x\n", data);
|
||||
|
||||
m_sdcard->spi_ss_w(BIT(data, 1));
|
||||
m_spi_clock_sysclk = bool(BIT(data, 0));
|
||||
|
||||
m_spi_clock_state = false;
|
||||
m_spi_clock->adjust(attotime::never);
|
||||
}
|
||||
|
||||
uint8_t vtech_sdloader_device::sdio_r()
|
||||
{
|
||||
logerror("sdio_r\n");
|
||||
return 0xff;
|
||||
LOGMASKED(LOG_SPI, "sdio_r: %02x\n", m_in_latch);
|
||||
|
||||
return m_in_latch;
|
||||
}
|
||||
|
||||
void vtech_sdloader_device::sdio_w(uint8_t data)
|
||||
{
|
||||
logerror("sdio_w: %02x\n", data);
|
||||
LOGMASKED(LOG_SPI, "sdio_w: %02x\n", data);
|
||||
|
||||
m_out_latch = data;
|
||||
m_spi_clock_cycles = 8;
|
||||
|
||||
// TODO: too fast, also slightly different on vz200
|
||||
// code only waits for a single NOP before sending the next byte
|
||||
if (m_spi_clock_sysclk)
|
||||
m_spi_clock->adjust(attotime::from_hz(17.734470_MHz_XTAL / 1.5), 0, attotime::from_hz(17.734470_MHz_XTAL / 1.5));
|
||||
else
|
||||
m_spi_clock->adjust(attotime::from_hz(100_kHz_XTAL), 0, attotime::from_hz(100_kHz_XTAL));
|
||||
}
|
||||
|
||||
void vtech_sdloader_device::mode_w(uint8_t data)
|
||||
{
|
||||
logerror("Switching to %s mode\n", BIT(data, 0) ? "VZ-300" : "VZ-200");
|
||||
LOG("Switching to %s mode\n", BIT(data, 0) ? "VZ-300" : "VZ-200");
|
||||
m_vz300_mode = bool(BIT(data, 0));
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "machine/spi_sdcard.h"
|
||||
#include "memexp.h"
|
||||
|
||||
|
||||
|
@ -30,6 +31,7 @@ public:
|
|||
|
||||
protected:
|
||||
virtual const tiny_rom_entry *device_rom_region() const override;
|
||||
virtual void device_add_mconfig(machine_config &config) override;
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
|
||||
|
@ -37,10 +39,14 @@ protected:
|
|||
virtual void io_map(address_map &map) override;
|
||||
|
||||
private:
|
||||
required_device<spi_sdcard_device> m_sdcard;
|
||||
required_memory_bank m_dosbank;
|
||||
memory_view m_dosview;
|
||||
memory_bank_creator m_expbank;
|
||||
|
||||
TIMER_CALLBACK_MEMBER(spi_clock);
|
||||
void spi_miso_w(int state);
|
||||
|
||||
void mapper_w(uint8_t data);
|
||||
void sdcfg_w(uint8_t data);
|
||||
uint8_t sdio_r();
|
||||
|
@ -50,6 +56,14 @@ private:
|
|||
uint8_t exp_ram_r(offs_t offset);
|
||||
void exp_ram_w(offs_t offset, uint8_t data);
|
||||
|
||||
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<uint8_t[]> m_ram;
|
||||
bool m_vz300_mode;
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue