casio/fp1100.cpp: add expansion slots, FP-1060I/O and RAMPACK

This commit is contained in:
angelosa 2024-07-18 10:44:31 +02:00
parent 5fd57331a7
commit 5f71cfecb7
10 changed files with 569 additions and 8 deletions

View File

@ -1415,6 +1415,25 @@ if (BUSES["FMT_SCSI"]~=null) then
}
end
---------------------------------------------------
--
--@src/devices/bus/fp1000/fp1000_exp.h,BUSES["FP1000"] = true
---------------------------------------------------
if (BUSES["FP1000"]~=null) then
files {
MAME_DIR .. "src/devices/bus/fp1000/fp1000_exp.cpp",
MAME_DIR .. "src/devices/bus/fp1000/fp1000_exp.h",
MAME_DIR .. "src/devices/bus/fp1000/fp1030_rampack.cpp",
MAME_DIR .. "src/devices/bus/fp1000/fp1030_rampack.h",
MAME_DIR .. "src/devices/bus/fp1000/fp1060io.cpp",
MAME_DIR .. "src/devices/bus/fp1000/fp1060io.h",
MAME_DIR .. "src/devices/bus/fp1000/fp1060io_exp.cpp",
MAME_DIR .. "src/devices/bus/fp1000/fp1060io_exp.h",
}
end
---------------------------------------------------
--
--@src/devices/bus/gamate/slot.h,BUSES["GAMATE"] = true

View File

@ -0,0 +1,99 @@
// license:BSD-3-Clause
// copyright-holders:Angelo Salese
#include "emu.h"
#include "fp1000_exp.h"
DEFINE_DEVICE_TYPE(FP1000_EXP_SLOT, fp1000_exp_slot_device, "fp1000_exp_slot", "FP-1000/FP-1100 Expansion Slot")
fp1000_exp_slot_device::fp1000_exp_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, FP1000_EXP_SLOT, tag, owner, clock)
, device_single_card_slot_interface<device_fp1000_exp_interface>(mconfig, *this)
, m_iospace(*this, finder_base::DUMMY_TAG, -1)
{
}
fp1000_exp_slot_device::~fp1000_exp_slot_device()
{
}
void fp1000_exp_slot_device::device_start()
{
}
void fp1000_exp_slot_device::device_config_complete()
{
m_dev = get_card_device();
}
device_fp1000_exp_interface::device_fp1000_exp_interface(const machine_config &mconfig, device_t &device)
: device_interface(device, "fp1000exp")
{
m_slot = dynamic_cast<fp1000_exp_slot_device *>(device.owner());
}
device_fp1000_exp_interface::~device_fp1000_exp_interface()
{
}
void device_fp1000_exp_interface::interface_pre_start()
{
if (!m_slot->started())
throw device_missing_dependencies();
}
void device_fp1000_exp_interface::interface_post_start()
{
// m_slot->install_io_device(*this, &device_fp1000_exp_interface::io_map);
m_slot->select_w(false);
}
void fp1000_exp_slot_device::remap_cb()
{
if (!m_main_enable || m_dev == nullptr)
{
logerror("%s: unmap\n", machine().describe_context());
m_iospace->unmap_readwrite(0x0000, 0xfeff);
m_iospace->unmap_readwrite(0xff00, 0xff7f);
}
else
{
logerror("%s: map\n", machine().describe_context());
m_iospace->install_readwrite_handler(0xff00, 0xff7f, read8sm_delegate(*m_dev, FUNC(device_fp1000_exp_interface::id_r)), write8sm_delegate(*this, FUNC(fp1000_exp_slot_device::main_cs_w)));
m_dev->remap_cb();
}
}
void fp1000_exp_slot_device::select_w(bool enable)
{
m_main_enable = enable;
remap_cb();
}
void fp1000_exp_slot_device::main_cs_w(offs_t offset, u8 data)
{
m_dev->cs_w(offset, data);
m_dev->remap_cb();
}
fp1000_exp_device::fp1000_exp_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_fp1000_exp_interface(mconfig, *this)
{
}
void fp1000_exp_device::device_start()
{
}
// slot devices
#include "fp1060io.h"
void fp1000_exp_devices(device_slot_interface &device)
{
device.option_add("fp1060io", FP1060IO);
// TODO: other options, if any
}

View File

@ -0,0 +1,85 @@
// license:BSD-3-Clause
// copyright-holders:Angelo Salese
#ifndef MAME_BUS_FP1000_EXP_H
#define MAME_BUS_FP1000_EXP_H
#pragma once
class device_fp1000_exp_interface;
class fp1000_exp_device;
class fp1000_exp_slot_device : public device_t, public device_single_card_slot_interface<device_fp1000_exp_interface>
{
friend class device_fp1000_exp_interface;
public:
// construction/destruction
template <typename T>
fp1000_exp_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, T &&opts, char const *dflt)
: fp1000_exp_slot_device(mconfig, tag, owner, (uint32_t)0)
{
option_reset();
opts(*this);
set_default_option(dflt);
set_fixed(false);
}
fp1000_exp_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
virtual ~fp1000_exp_slot_device();
template <typename T> void set_iospace(T &&tag, int spacenum) { m_iospace.set_tag(std::forward<T>(tag), spacenum); }
address_space &iospace() const { return *m_iospace; }
void select_w(bool enable);
protected:
virtual void device_start() override;
virtual void device_config_complete() override;
private:
required_address_space m_iospace;
void remap_cb();
void main_cs_w(offs_t offset, u8 data);
bool m_main_enable = false;
device_fp1000_exp_interface *m_dev;
};
class device_fp1000_exp_interface : public device_interface
{
public:
// construction/destruction
virtual ~device_fp1000_exp_interface();
virtual void cs_w(offs_t offset, u8 data) = 0;
virtual u8 id_r(offs_t offset) = 0;
virtual void remap_cb() = 0;
protected:
device_fp1000_exp_interface(const machine_config &mconfig, device_t &device);
virtual void interface_pre_start() override;
virtual void interface_post_start() override;
fp1000_exp_slot_device *m_slot;
};
class fp1000_exp_device : public device_t, public device_fp1000_exp_interface
{
public:
// construction/destruction
fp1000_exp_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
protected:
// virtual void device_add_mconfig(machine_config &config) override;
virtual void device_start() override;
};
// device type definition
DECLARE_DEVICE_TYPE(FP1000_EXP_SLOT, fp1000_exp_slot_device)
void fp1000_exp_devices(device_slot_interface &device);
#endif // MAME_MACHINE_FP1000_EXP_H

View File

@ -0,0 +1,48 @@
// license:BSD-3-Clause
// copyright-holders:Angelo Salese
/**************************************************************************************************
FP-1030 RAMPACK
FILES"PACK<x>:" where <x> is the designated slot number 0-7
LOAD"PACKx:<filename>"
RUN
**************************************************************************************************/
#include "emu.h"
#include "fp1030_rampack.h"
DEFINE_DEVICE_TYPE(FP1030_RAMPACK, fp1030_rampack_device, "fp1030_rampack", "FP-1030 RAMPACK")
fp1030_rampack_device::fp1030_rampack_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: fp1060io_exp_device(mconfig, FP1030_RAMPACK, tag, owner, clock)
, m_nvram(*this, "nvram")
{
}
void fp1030_rampack_device::io_map(address_map &map)
{
map(0x0000, 0x3fff).lrw8(
NAME([this](offs_t offset) { return m_nvram_ptr[offset & 0x3fff]; }),
NAME([this](offs_t offset, uint8_t data) { m_nvram_ptr[offset & 0x3fff] = data; })
);
}
void fp1030_rampack_device::device_add_mconfig(machine_config &config)
{
// C-16K CMOS, 8 banks with 0x800 length
NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_0);
}
void fp1030_rampack_device::device_start()
{
const u32 nvram_size = 0x4000;
m_nvram_ptr = std::make_unique<uint8_t[]>(nvram_size);
m_nvram->set_base(m_nvram_ptr.get(), nvram_size);
save_pointer(NAME(m_nvram_ptr), nvram_size);
}
void fp1030_rampack_device::device_reset()
{
}

View File

@ -0,0 +1,34 @@
// license:BSD-3-Clause
// copyright-holders:Angelo Salese
#ifndef MAME_BUS_FP1030_RAMPACK_H
#define MAME_BUS_FP1030_RAMPACK_H
#pragma once
#include "fp1060io_exp.h"
#include "machine/nvram.h"
class fp1030_rampack_device : public fp1060io_exp_device
{
public:
fp1030_rampack_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
virtual void io_map(address_map &map) override;
virtual u8 get_id() override { return 0x01; };
protected:
virtual void device_start() override;
virtual void device_reset() override;
private:
virtual void device_add_mconfig(machine_config &config) override;
required_device<nvram_device> m_nvram;
std::unique_ptr<uint8_t[]> m_nvram_ptr;
};
DECLARE_DEVICE_TYPE(FP1030_RAMPACK, fp1030_rampack_device)
#endif // MAME_BUS_FP1030_RAMPACK_H

View File

@ -0,0 +1,66 @@
// license:BSD-3-Clause
// copyright-holders:Angelo Salese
#include "emu.h"
#include "fp1060io.h"
DEFINE_DEVICE_TYPE(FP1060IO, fp1060io_device, "fp1060io", "FP-1060I/O Expansion Box")
fp1060io_device::fp1060io_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: fp1000_exp_device(mconfig, FP1060IO, tag, owner, clock)
, m_subslot(*this, "%u", 0U)
{
}
void fp1060io_device::device_add_mconfig(machine_config &config)
{
for (auto slot : m_subslot)
{
// default is just for CLI usability, what a retail '1060 gives back on its own is unconfirmed.
FP1060IO_EXP_SLOT(config, slot, fp1060io_slot_devices, "rampack");
}
}
void fp1060io_device::device_start()
{
}
void fp1060io_device::device_reset()
{
}
u8 fp1060io_device::id_r(offs_t offset)
{
logerror("%s: ID select %02x\n", machine().describe_context(), m_slot_select);
if (m_slot_select & 0xc)
return 0xff;
const auto dev = m_subslot[m_slot_select]->m_dev;
//logerror("\texists: %d\n", dev != nullptr);
if (dev == nullptr)
return 0xff;
return dev->get_id();
}
void fp1060io_device::cs_w(offs_t offset, u8 data)
{
m_slot_select = data & 0xf;
}
void fp1060io_device::remap_cb()
{
logerror("%s: remap_cb %02x\n", machine().describe_context(), m_slot_select);
if (m_slot_select & 0xc)
m_slot->iospace().unmap_readwrite(0x0000, 0xfeff);
else
{
const auto dev = m_subslot[m_slot_select]->m_dev;
//logerror("\texists %d\n", dev != nullptr);
if (dev == nullptr)
m_slot->iospace().unmap_readwrite(0x0000, 0xfeff);
else
m_slot->iospace().install_device(0x0000, 0xfeff, *m_subslot[m_slot_select]->m_dev, &device_fp1060io_exp_interface::io_map);
}
}

View File

@ -0,0 +1,37 @@
// license:BSD-3-Clause
// copyright-holders:Angelo Salese
#ifndef MAME_BUS_FP1060IO_H
#define MAME_BUS_FP1060IO_H
#pragma once
#include "fp1000_exp.h"
#include "fp1060io_exp.h"
class fp1060io_device : public fp1000_exp_device
//, public device_single_card_slot_interface<device_fp1060io_slot_interface>
{
public:
fp1060io_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
virtual void cs_w(offs_t offset, u8 data) override;
virtual u8 id_r(offs_t offset) override;
virtual void remap_cb() override;
protected:
virtual void device_start() override;
virtual void device_reset() override;
private:
virtual void device_add_mconfig(machine_config &config) override;
required_device_array<fp1060io_exp_slot_device, 4> m_subslot;
u8 m_slot_select = 0;
};
DECLARE_DEVICE_TYPE(FP1060IO, fp1060io_device)
#endif // MAME_BUS_FP1060IO_H

View File

@ -0,0 +1,87 @@
// license:BSD-3-Clause
// copyright-holders:Angelo Salese
/**************************************************************************************************
FP-1060I/O Expansion Slot
List of known devices:
- FP-1020FD2 (FDC uPD765, 2x 5.25 floppy DSDD, id = 0x04)
- FP-1021FD1 (FDC, 1x 5.25 floppy FP-200 compatible 70kb (?))
- FP-1022FD1 (FDC, 1x 5.25)
- FP-1023FD1 (Same as 1020 with 1x drive?)
- FP-1024FD2 (FDC, 2x floppy 2HD)
- FP-1030 (RAMPACK, id = 0x01)
- FP-1031 (ROMPACK, id = 0x00)
\- One of the ROMPACKs has undumped Test Mode (cfr. page 94 of service manual)
- FP-1032K (Kanji ROM pack, unknown id)
- FP-1035RS (RS-232C, id = 0x02)
**************************************************************************************************/
#include "emu.h"
#include "fp1060io_exp.h"
DEFINE_DEVICE_TYPE(FP1060IO_EXP_SLOT, fp1060io_exp_slot_device, "fp1060io_exp_slot", "FP-1060I/O Expansion Slot")
fp1060io_exp_slot_device::fp1060io_exp_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, FP1060IO_EXP_SLOT, tag, owner, clock)
, device_single_card_slot_interface<device_fp1060io_exp_interface>(mconfig, *this)
{
}
fp1060io_exp_slot_device::~fp1060io_exp_slot_device()
{
}
void fp1060io_exp_slot_device::device_start()
{
}
void fp1060io_exp_slot_device::device_config_complete()
{
m_dev = get_card_device();
}
device_fp1060io_exp_interface::device_fp1060io_exp_interface(const machine_config &mconfig, device_t &device)
: device_interface(device, "fp1060ioexp")
{
m_slot = dynamic_cast<fp1060io_exp_slot_device *>(device.owner());
}
device_fp1060io_exp_interface::~device_fp1060io_exp_interface()
{
}
void device_fp1060io_exp_interface::interface_pre_start()
{
if (!m_slot->started())
throw device_missing_dependencies();
}
void device_fp1060io_exp_interface::interface_post_start()
{
// m_slot->install_io_device(*this, &device_fp1000_exp_interface::io_map);
// m_slot->select_w(false);
}
fp1060io_exp_device::fp1060io_exp_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_fp1060io_exp_interface(mconfig, *this)
{
}
void fp1060io_exp_device::device_start()
{
}
#include "fp1030_rampack.h"
void fp1060io_slot_devices(device_slot_interface &device)
{
device.option_add("rampack", FP1030_RAMPACK);
}

View File

@ -0,0 +1,74 @@
// license:BSD-3-Clause
// copyright-holders:Angelo Salese
#ifndef MAME_BUS_FP1060IO_EXP_H
#define MAME_BUS_FP1060IO_EXP_H
#pragma once
class device_fp1060io_exp_interface;
class fp1060io_exp_device;
class fp1060io_exp_slot_device : public device_t, public device_single_card_slot_interface<device_fp1060io_exp_interface>
{
friend class device_fp1060io_exp_interface;
public:
// construction/destruction
template <typename T>
fp1060io_exp_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, T &&opts, char const *dflt)
: fp1060io_exp_slot_device(mconfig, tag, owner, (uint32_t)0)
{
option_reset();
opts(*this);
set_default_option(dflt);
set_fixed(false);
}
fp1060io_exp_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
virtual ~fp1060io_exp_slot_device();
device_fp1060io_exp_interface *m_dev;
protected:
virtual void device_start() override;
virtual void device_config_complete() override;
//private:
};
class device_fp1060io_exp_interface : public device_interface
{
public:
// construction/destruction
virtual ~device_fp1060io_exp_interface();
virtual void io_map(address_map &map) = 0;
virtual u8 get_id() = 0;
protected:
device_fp1060io_exp_interface(const machine_config &mconfig, device_t &device);
virtual void interface_pre_start() override;
virtual void interface_post_start() override;
fp1060io_exp_slot_device *m_slot;
};
class fp1060io_exp_device : public device_t, public device_fp1060io_exp_interface
{
public:
// construction/destruction
fp1060io_exp_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
protected:
// virtual void device_add_mconfig(machine_config &config) override;
virtual void device_start() override;
};
void fp1060io_slot_devices(device_slot_interface &device);
DECLARE_DEVICE_TYPE(FP1060IO_EXP_SLOT, fp1060io_exp_slot_device)
#endif // MAME_BUS_FP1060IO_EXP_H

View File

@ -2,23 +2,24 @@
// copyright-holders:Angelo Salese
/**************************************************************************************************
Casio FP-1100 (GX-205)
Casio FP-1000 / FP-1100 (GX-205)
TODO:
- Keyboard not working, should trigger INTF0 on key pressed (for PF only), main CPU receives
garbage from sub (command protocol 0x04 -> <scancode> -> 0x00 -> 0x00)
As a _ugly_ workaround you can intercept ASCII scancodes from main CPU with bp d18 A=<value> with
any emu::keypost trigger.
- Memory maps and machine configuration for FP-1000 with reduced VRAM;
- Unimplemented instruction PER triggered in sub CPU;
- SCREEN 1 mode has heavy corrupted GFXs and runs at half speed, interlace mode?
- Cassette Load is really not working, uses a complex 6 pin discrete circuitry;
- Sub CPU needs proper WAIT line from uPD7801;
- Main CPU waitstates;
- bus slots (FP-1060I/O, 1 slot can take up to 4 sub slots below):
- FP-1020FD (FDC uPD765, 2x 5.25 floppy DSDD, id = 0x04)
- FP-1030 (RAMPACK, id = 0x01)
- FP-1031 (ROMPACK, id = 0x00)
- FP-1035RS (RS-232C, id = 0x02)
- One of the ROMPACKs has undumped Test Mode (cfr. page 94 of service manual)
- centronics options (likely):
- FP-1011PL (plotter)
- FP-1012PR (OEM Epson MX-80)
- FP-1014PRK (Kanji printer)
- FP-1017PR (OEM Epson MX-160)
===================================================================================================
@ -46,6 +47,7 @@ The keyboard is a separate unit. It contains a beeper.
#include "emu.h"
#include "bus/centronics/ctronics.h"
#include "bus/fp1000/fp1000_exp.h"
#include "cpu/upd7810/upd7810.h"
#include "cpu/z80/z80.h"
#include "imagedev/cassette.h"
@ -84,6 +86,7 @@ public:
, m_beep(*this, "beeper")
, m_centronics(*this, "centronics")
, m_cassette(*this, "cassette")
, m_slot(*this, "slot.%u", 0)
{ }
void fp1100(machine_config &config);
@ -105,6 +108,7 @@ private:
required_device<beep_device> m_beep;
required_device<centronics_device> m_centronics;
required_device<cassette_image_device> m_cassette;
required_device_array<fp1000_exp_slot_device, 2> m_slot;
void main_map(address_map &map);
void io_map(address_map &map);
@ -202,7 +206,9 @@ other bits not used
void fp1100_state::main_bank_w(u8 data)
{
m_iplview.select(BIT(data, 1));
// m_slot_num = (m_slot_num & 3) | ((data & 1) << 2); //??
const u8 slot_select = BIT(data, 0);
m_slot[slot_select ^ 1]->select_w(false);
m_slot[slot_select]->select_w(true);
}
/*
@ -764,6 +770,12 @@ void fp1100_state::fp1100(machine_config &config)
SPEAKER(config, "mono").front_center();
BEEP(config, "beeper", 950) // guess
.add_route(ALL_OUTPUTS, "mono", 0.50); // inside the keyboard
for (auto slot : m_slot)
{
FP1000_EXP_SLOT(config, slot, fp1000_exp_devices, nullptr);
slot->set_iospace(m_maincpu, AS_IO);
}
}
// TODO: chargen, keyboard ROM and key tops can be substituted on actual FP-1000/FP-1100