add preliminary driver for Casio FZ series samplers (#13623)

- implement internal serial interrupt for V50
- support alternate screen dimensions for HD44352

New NOT_WORKING machine
----------
Casio FZ-1 Digital Sampling Synthesizer [Rainer Buchty, Devin Acker]

New NOT_WORKING clone
----------
Casio FZ-10M Digital Sampling Synthesizer Module [Tom Virostek, Devin Acker]
Casio FZ-20M Digital Sampling Synthesizer Module [BCM, Devin Acker]
This commit is contained in:
Devin Acker 2025-04-29 19:52:50 -04:00 committed by GitHub
parent 3131c64672
commit 1ac2788ab8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 736 additions and 30 deletions

View File

@ -320,7 +320,7 @@ void v50_base_device::OPCN_w(u8 data)
m_OPCN = data & 0x0f;
m_tout1_callback((data & 0x03) == 0x03 ? m_tout1 : 1);
m_icu->ir1_w(BIT(data, 2) ? 0 : m_intp1);
m_icu->ir1_w(BIT(data, 2) ? m_sint : m_intp1);
m_icu->ir2_w(BIT(data, 3) ? m_tout1 : m_intp2);
}
@ -333,6 +333,13 @@ void v50_base_device::tout1_w(int state)
m_icu->ir2_w(state);
}
void v50_base_device::sint_w(int state)
{
m_sint = state;
if (BIT(m_OPCN, 2))
m_icu->ir1_w(state);
}
void v50_base_device::device_reset()
{
nec_common_device::device_reset();
@ -348,8 +355,11 @@ void v50_base_device::device_start()
set_irq_acknowledge_callback(*m_icu, FUNC(v5x_icu_device::inta_cb));
m_scu->write_cts(0);
save_item(NAME(m_OPCN));
save_item(NAME(m_tout1));
save_item(NAME(m_sint));
save_item(NAME(m_intp1));
save_item(NAME(m_intp2));
}
@ -502,6 +512,8 @@ void v50_base_device::device_add_mconfig(machine_config &config)
m_tcu->out_handler<1>().set(m_scu, FUNC(v5x_scu_device::write_rxc));
m_tcu->out_handler<1>().append(m_scu, FUNC(v5x_scu_device::write_txc));
m_tcu->out_handler<1>().append(FUNC(v50_base_device::tout1_w));
m_scu->sint_handler().set(FUNC(v50_base_device::sint_w));
}
device_memory_interface::space_config_vector v50_base_device::memory_space_config() const

View File

@ -36,12 +36,7 @@ public:
// SCU
auto txd_handler_cb() { return m_scu.lookup()->txd_handler(); }
auto dtr_handler_cb() { return m_scu.lookup()->dtr_handler(); }
auto rts_handler_cb() { return m_scu.lookup()->rts_handler(); }
auto rxrdy_handler_cb() { return m_scu.lookup()->rxrdy_handler(); }
auto txrdy_handler_cb() { return m_scu.lookup()->txrdy_handler(); }
auto txempty_handler_cb() { return m_scu.lookup()->txempty_handler(); }
auto syndet_handler_cb() { return m_scu.lookup()->syndet_handler(); }
void rxd_w(int state) { m_scu->write_rxd(state); }
protected:
device_v5x_interface(const machine_config &mconfig, nec_common_device &device, bool is_16bit);
@ -190,14 +185,16 @@ protected:
private:
void tout1_w(int state);
void sint_w(int state);
devcb_write_line m_tout1_callback;
devcb_read8 m_icu_slave_ack;
u8 m_OPCN;
bool m_tout1;
bool m_intp1;
bool m_intp2;
u8 m_tout1;
u8 m_sint;
u8 m_intp1;
u8 m_intp2;
};
class v40_device : public v50_base_device
@ -239,6 +236,14 @@ public:
template <unsigned Timer> auto tout_handler() { return m_tcu.lookup()->out_handler<Timer>(); }
// SCU
auto dtr_handler_cb() { return m_scu.lookup()->dtr_handler(); }
auto rts_handler_cb() { return m_scu.lookup()->rts_handler(); }
auto rxrdy_handler_cb() { return m_scu.lookup()->rxrdy_handler(); }
auto txrdy_handler_cb() { return m_scu.lookup()->txrdy_handler(); }
auto txempty_handler_cb() { return m_scu.lookup()->txempty_handler(); }
auto syndet_handler_cb() { return m_scu.lookup()->syndet_handler(); }
protected:
v53_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);

View File

@ -80,6 +80,7 @@ i8251_device::i8251_device(const machine_config &mconfig, const char *tag, devic
v5x_scu_device::v5x_scu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: i8251_device(mconfig, V5X_SCU, tag, owner, clock)
, m_sint_handler(*this)
{
}
@ -126,15 +127,14 @@ void i8251_device::device_start()
void i8251_device::update_rx_ready()
{
int state = m_status & I8251_STATUS_RX_READY;
// masked?
if (!BIT(m_command, 2))
state = 0;
m_rxrdy_handler(state != 0);
m_rxrdy_handler(rxrdy_r());
}
void v5x_scu_device::update_rx_ready()
{
i8251_device::update_rx_ready();
sint_bit_w<0>(rxrdy_r());
}
/*-------------------------------------------------
@ -376,21 +376,20 @@ void i8251_device::transmit_clock()
void i8251_device::update_tx_ready()
{
/* clear tx ready state */
int tx_ready;
/* tx ready output is set if:
DB Buffer Empty &
CTS is set &
Transmit enable is 1
*/
tx_ready = is_tx_enabled() && (m_status & I8251_STATUS_TX_READY) != 0;
m_txrdy_handler(tx_ready);
m_txrdy_handler(txrdy_r());
}
void v5x_scu_device::update_tx_ready()
{
i8251_device::update_tx_ready();
sint_bit_w<1>(txrdy_r());
}
/*-------------------------------------------------
update_tx_empty
@ -875,10 +874,22 @@ int i8251_device::txrdy_r()
return is_tx_enabled() && (m_status & I8251_STATUS_TX_READY) != 0;
}
int i8251_device::rxrdy_r()
{
// masked?
if (!BIT(m_command, 2))
return 0;
return (m_status & I8251_STATUS_RX_READY) != 0;
}
void v5x_scu_device::device_start()
{
i8251_device::device_start();
m_sint = 0;
save_item(NAME(m_sint));
save_item(NAME(m_simk));
}
@ -890,6 +901,11 @@ void v5x_scu_device::device_reset()
i8251_device::device_reset();
}
void v5x_scu_device::update_sint()
{
m_sint_handler((m_sint & ~m_simk) != 0);
}
u8 v5x_scu_device::read(offs_t offset)
{
u8 data = 0;

View File

@ -46,6 +46,7 @@ public:
void write_syn(int state);
int txrdy_r();
int rxrdy_r();
protected:
enum
@ -74,8 +75,8 @@ protected:
void receive_character(uint8_t ch);
void update_rx_ready();
void update_tx_ready();
virtual void update_rx_ready();
virtual void update_tx_ready();
void update_tx_empty();
void transmit_clock();
void receive_clock();
@ -153,6 +154,8 @@ public:
// construction/destruction
v5x_scu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
auto sint_handler() { return m_sint_handler.bind(); }
virtual uint8_t read(offs_t offset) override;
virtual void write(offs_t offset, uint8_t data) override;
@ -161,11 +164,29 @@ protected:
virtual void device_start() override ATTR_COLD;
virtual void device_reset() override ATTR_COLD;
// TODO: currently unimplemented interrupt masking
virtual void update_rx_ready() override;
virtual void update_tx_ready() override;
template<int Bit>
void sint_bit_w(int state)
{
if (state)
m_sint |= (1 << Bit);
else
m_sint &= ~(1 << Bit);
update_sint();
}
u8 simk_r() { return m_simk; }
void simk_w(u8 data) { m_simk = data; }
void simk_w(u8 data) { m_simk = data; update_sint(); }
private:
void update_sint();
devcb_write_line m_sint_handler;
u8 m_sint;
u8 m_simk;
};

View File

@ -9,6 +9,8 @@
#include "emu.h"
#include "hd44352.h"
#include "screen.h"
#define LCD_BYTE_INPUT 0x01
#define LCD_BYTE_OUTPUT 0x02
#define LCD_CHAR_OUTPUT 0x03
@ -132,6 +134,11 @@ uint32_t hd44352_device::screen_update(screen_device &screen, bitmap_ind16 &bitm
if (m_control_lines&0x80 && m_lcd_on)
{
for (int a=0; a<2; a++)
{
// drivers can be arranged as 96x64 or 192x32 when char width is 6
const unsigned sx = (a * 16 * cw) % screen.width();
const unsigned sy = (a * 32) % screen.height();
for (int py=0; py<4; py++)
for (int px=0; px<16; px++)
if (BIT(m_cursor_status, 4) && px == m_cursor_x && py == m_cursor_y && a == m_cursor_lcd)
@ -142,7 +149,7 @@ uint32_t hd44352_device::screen_update(screen_device &screen, bitmap_ind16 &bitm
uint8_t d = compute_newval((m_cursor_status>>5) & 0x07, m_video_ram[a][py*16*cw + px*cw + c + m_scroll * 48], m_cursor[c]);
for (int b=0; b<8; b++)
{
bitmap.pix(py*8 + b, a*cw*16 + px*cw + c) = BIT(d, 7-b);
bitmap.pix(sy + py*8 + b, sx + px*cw + c) = BIT(d, 7-b);
}
}
}
@ -153,10 +160,11 @@ uint32_t hd44352_device::screen_update(screen_device &screen, bitmap_ind16 &bitm
uint8_t d = m_video_ram[a][py*16*cw + px*cw + c + m_scroll * 48];
for (int b=0; b<8; b++)
{
bitmap.pix(py*8 + b, a*cw*16 + px*cw + c) = BIT(d, 7-b);
bitmap.pix(sy + py*8 + b, sx + px*cw + c) = BIT(d, 7-b);
}
}
}
}
}
return 0;

639
src/mame/casio/fz1.cpp Normal file
View File

@ -0,0 +1,639 @@
// license:BSD-3-Clause
// copyright-holders:Devin Acker
/*
Driver for Casio FZ-1 and FZ-10M/20M samplers
Custom sound + video hardware consists of:
- GAA (uPD65081G-012): address generator for sample RAM
- GAB (uPD65042G-052): timing generator for PCM interrupt and sample/hold signals
- GAS (uPD65012G-074): bus arbiter & DRAM refresh signal generator
- GAX (MB653121): demultiplexes sample RAM output to two DACs
- 4x MB87186 DCF/DCA (two inputs/outputs each)
- GAL (uPD65012G-046): generates data & strobe signals for LCD controller
- HD44350 LCD controller + 2x HD44251 segment drivers
Floppy drive: Panasonic JU-386 @ 360 rpm
Disk format: 2HD, 80 tracks * 8 sectors * 1024 bytes
A good deal of hardware and programming info is available courtesy of Rainer Buchty:
http://www.buchty.net/casio/
*/
#include "emu.h"
#include "bus/midi/midiinport.h"
#include "bus/midi/midioutport.h"
#include "bus/nscsi/hd.h"
#include "cpu/mcs48/mcs48.h"
#include "cpu/nec/v5x.h"
#include "machine/bankdev.h"
#include "machine/mb87030.h"
#include "machine/i8255.h"
#include "machine/msm6200.h"
#include "machine/ram.h"
#include "machine/upd765.h"
#include "video/hd44352.h"
#include "emupal.h"
#include "screen.h"
#include "speaker.h"
namespace {
class fz1_state : public driver_device
{
public:
fz1_state(const machine_config &mconfig, device_type type, const char *tag)
: driver_device(mconfig, type, tag)
, m_maincpu(*this, "maincpu")
, m_subcpu(*this, "subcpu")
, m_ram(*this, "ram")
, m_ram_bank(*this, "ram_bank")
, m_io(*this, "io%u", 0u)
, m_kbd(*this, "kbd")
, m_lcdc(*this, "lcdc")
, m_keys(*this, "SC%u", 0u)
, m_analog(*this, "AN%u", 0u)
, m_led(*this, "led%u", 0u)
{ }
void fz1(machine_config &config);
void fz10m(machine_config &config);
void fz20m(machine_config &config);
void keys_w(u8 val) { m_key_sel = val; }
u8 keys_r();
void adc_sel_w(u8 val) { m_adc_sel = val; }
u8 adc_latch_r();
u8 adc_r() { return m_adc_value; }
u8 lcd_ready_r() { return m_lcd_ready; }
int cont49_r();
int sync49_r() { return m_sync49; }
protected:
virtual void machine_start() override ATTR_COLD;
virtual void machine_reset() override ATTR_COLD;
private:
void maincpu_map(address_map &map) ATTR_COLD;
void fz10m_io_map(address_map &map) ATTR_COLD;
void fz20m_io_map(address_map &map) ATTR_COLD;
void fz1_io_map(address_map &map) ATTR_COLD;
void subcpu_map(address_map &map) ATTR_COLD;
void gal_w(u8 data);
void led_w(u8 data);
// main CPU / key MCU comm methods
u8 subcpu_r();
void sub_p2_w(u8 data);
required_device<v50_device> m_maincpu;
optional_device<i8049_device> m_subcpu;
required_device<ram_device> m_ram;
required_device<address_map_bank_device> m_ram_bank;
required_device_array<i8255_device, 2> m_io;
optional_device<msm6200_device> m_kbd;
required_device<hd44352_device> m_lcdc;
required_ioport_array<4> m_keys;
optional_ioport_array<8> m_analog;
output_finder<5> m_led;
u8 m_key_sel;
u8 m_adc_sel;
u8 m_adc_value;
u8 m_sub_p2, m_sync49;
u8 m_lcd_ready;
u8 m_lcd_data;
u8 m_lcd_data_phase;
u8 m_lcd_nibble;
};
/**************************************************************************/
static INPUT_PORTS_START(fz10m)
PORT_START("SC0")
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("Keypad 0") PORT_CODE(KEYCODE_0_PAD)
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("Keypad 1") PORT_CODE(KEYCODE_1_PAD)
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("Keypad 2") PORT_CODE(KEYCODE_2_PAD)
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("Keypad 3") PORT_CODE(KEYCODE_3_PAD)
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("Keypad 4") PORT_CODE(KEYCODE_4_PAD)
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("Keypad 5") PORT_CODE(KEYCODE_5_PAD)
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("Keypad 6") PORT_CODE(KEYCODE_6_PAD)
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("Keypad 7") PORT_CODE(KEYCODE_7_PAD)
PORT_START("SC1")
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("Keypad 8") PORT_CODE(KEYCODE_8_PAD)
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("Keypad 9") PORT_CODE(KEYCODE_9_PAD)
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("Keypad + / Yes") PORT_CODE(KEYCODE_PLUS_PAD)
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("Keypad - / No") PORT_CODE(KEYCODE_MINUS_PAD)
PORT_BIT(0xf0, IP_ACTIVE_LOW, IPT_UNUSED)
PORT_START("SC2")
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("Cursor Up") PORT_CODE(KEYCODE_UP)
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("Cursor Down") PORT_CODE(KEYCODE_DOWN)
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("Cursor Right") PORT_CODE(KEYCODE_RIGHT)
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("Cursor Left") PORT_CODE(KEYCODE_LEFT)
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("Enter") PORT_CODE(KEYCODE_ENTER)
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("Escape") PORT_CODE(KEYCODE_BACKSPACE)
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("Display")
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_UNUSED)
PORT_START("SC3")
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("Play")
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("Modify")
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("Call/Set Menu")
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("Transpose")
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("Tune")
PORT_BIT(0xe0, IP_ACTIVE_LOW, IPT_UNUSED)
PORT_START("IO1_PB")
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_CUSTOM) // GAA ready
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_CUSTOM) // GAB ready
PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_CUSTOM) PORT_READ_LINE_MEMBER(FUNC(fz1_state::lcd_ready_r))
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_CUSTOM) // ADC ready
PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_CUSTOM) PORT_READ_LINE_MEMBER(FUNC(fz1_state::cont49_r))
PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_CUSTOM) PORT_READ_LINE_MEMBER(FUNC(fz1_state::sync49_r))
PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_CUSTOM) // TODO
PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_CUSTOM) // TODO: FDC interrupt
PORT_START("IO2_PA")
PORT_BIT(0x03, IP_ACTIVE_HIGH, IPT_OUTPUT) PORT_WRITE_LINE_MEMBER(FUNC(fz1_state::keys_w));
PORT_BIT(0x1c, IP_ACTIVE_HIGH, IPT_OUTPUT) PORT_WRITE_LINE_MEMBER(FUNC(fz1_state::adc_sel_w));
PORT_BIT(0xe0, IP_ACTIVE_HIGH, IPT_OUTPUT) // TODO: floppy control
PORT_START("IO2_PB")
PORT_BIT(0x3f, IP_ACTIVE_HIGH, IPT_OUTPUT) PORT_WRITE_LINE_DEVICE_MEMBER("ram_bank", FUNC(address_map_bank_device::set_bank));
PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_OUTPUT) // sampling gain
PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_OUTPUT) // input sample rate
PORT_START("AN0")
PORT_BIT(0xff, 0x00, IPT_CUSTOM) // audio input peak level
PORT_START("AN5")
PORT_BIT(0xff, 0xff, IPT_POSITIONAL_V) PORT_NAME("Master Volume") PORT_SENSITIVITY(100) PORT_KEYDELTA(10) PORT_CENTERDELTA(0) PORT_PLAYER(2) PORT_CODE_DEC(JOYCODE_Y_DOWN_SWITCH) PORT_CODE_INC(JOYCODE_Y_UP_SWITCH)
PORT_START("AN6")
PORT_BIT(0xff, 0x80, IPT_POSITIONAL_V) PORT_NAME("Value") PORT_SENSITIVITY(100) PORT_KEYDELTA(10) PORT_CENTERDELTA(0) PORT_CODE_DEC(JOYCODE_Y_DOWN_SWITCH) PORT_CODE_INC(JOYCODE_Y_UP_SWITCH)
INPUT_PORTS_END
static INPUT_PORTS_START(fz1)
PORT_INCLUDE(fz10m)
PORT_START("kbd:KI8")
PORT_BIT(0x1, IP_ACTIVE_HIGH, IPT_UNUSED)
PORT_BIT(0x2, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("C6")
PORT_START("kbd:KI9")
PORT_BIT(0x1, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("B5")
PORT_BIT(0x2, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("A#5")
PORT_START("kbd:KI10")
PORT_BIT(0x1, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("A5")
PORT_BIT(0x2, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("G#5")
PORT_START("kbd:KI11")
PORT_BIT(0x1, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("G5")
PORT_BIT(0x2, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("F#5")
PORT_START("kbd:KI12")
PORT_BIT(0x1, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("F5")
PORT_BIT(0x2, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("E5")
PORT_START("kbd:KI13")
PORT_BIT(0x1, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("D#5")
PORT_BIT(0x2, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("D5")
PORT_START("kbd:KI14")
PORT_BIT(0x1, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("C#5")
PORT_BIT(0x2, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("C5")
PORT_START("kbd:KI15")
PORT_BIT(0x1, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("B4")
PORT_BIT(0x2, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("A#4")
PORT_START("kbd:KI16")
PORT_BIT(0x1, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("A4")
PORT_BIT(0x2, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("G#4")
PORT_START("kbd:KI17")
PORT_BIT(0x1, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("G4")
PORT_BIT(0x2, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("F#4")
PORT_START("kbd:KI18")
PORT_BIT(0x1, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("F4")
PORT_BIT(0x2, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("E4")
PORT_START("kbd:KI19")
PORT_BIT(0x1, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("D#4")
PORT_BIT(0x2, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("D4")
PORT_START("kbd:KI20")
PORT_BIT(0x1, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("C#4")
PORT_BIT(0x2, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("C4")
PORT_START("kbd:KI21")
PORT_BIT(0x1, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("B3")
PORT_BIT(0x2, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("A#3")
PORT_START("kbd:KI22")
PORT_BIT(0x1, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("A3")
PORT_BIT(0x2, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("G#3")
PORT_START("kbd:KI23")
PORT_BIT(0x1, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("G3")
PORT_BIT(0x2, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("F#3")
PORT_START("kbd:KI24")
PORT_BIT(0x1, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("F3")
PORT_BIT(0x2, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("E3")
PORT_START("kbd:KI25")
PORT_BIT(0x1, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("D#3")
PORT_BIT(0x2, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("D3")
PORT_START("kbd:KI26")
PORT_BIT(0x1, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("C#3")
PORT_BIT(0x2, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("C3")
PORT_START("kbd:KI27")
PORT_BIT(0x1, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("B2")
PORT_BIT(0x2, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("A#2")
PORT_START("kbd:KI28")
PORT_BIT(0x1, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("A2")
PORT_BIT(0x2, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("G#2")
PORT_START("kbd:KI29")
PORT_BIT(0x1, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("G2")
PORT_BIT(0x2, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("F#2")
PORT_START("kbd:KI30")
PORT_BIT(0x1, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("F2")
PORT_BIT(0x2, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("E2")
PORT_START("kbd:KI31")
PORT_BIT(0x1, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("D#2")
PORT_BIT(0x2, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("D2")
PORT_START("kbd:KI32")
PORT_BIT(0x1, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("C#2")
PORT_BIT(0x2, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("C2")
PORT_START("kbd:KI33")
PORT_BIT(0x1, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("B1")
PORT_BIT(0x2, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("A#1")
PORT_START("kbd:KI34")
PORT_BIT(0x1, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("A1")
PORT_BIT(0x2, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("G#1")
PORT_START("kbd:KI35")
PORT_BIT(0x1, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("G1")
PORT_BIT(0x2, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("F#1")
PORT_START("kbd:KI36")
PORT_BIT(0x1, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("F1")
PORT_BIT(0x2, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("E1")
PORT_START("kbd:KI37")
PORT_BIT(0x1, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("D#1")
PORT_BIT(0x2, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("D1")
PORT_START("kbd:KI38")
PORT_BIT(0x1, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("C#1")
PORT_BIT(0x2, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("C1")
PORT_START("kbd:VELOCITY")
PORT_BIT(0x3f, 0x3f, IPT_POSITIONAL_V) PORT_NAME("Key Velocity") PORT_SENSITIVITY(100) PORT_KEYDELTA(10) PORT_CENTERDELTA(0) PORT_PLAYER(7) PORT_CODE_DEC(JOYCODE_X_LEFT_SWITCH) PORT_CODE_INC(JOYCODE_X_RIGHT_SWITCH)
PORT_START("AN1")
PORT_BIT(0xff, 0xff, IPT_POSITIONAL_V) PORT_NAME("Volume Pedal") PORT_SENSITIVITY(100) PORT_KEYDELTA(10) PORT_CENTERDELTA(0) PORT_PLAYER(6) PORT_CODE_DEC(JOYCODE_Y_DOWN_SWITCH) PORT_CODE_INC(JOYCODE_Y_UP_SWITCH)
PORT_START("AN2")
PORT_BIT(0xff, 0xff, IPT_POSITIONAL_V) PORT_NAME("Aftertouch") PORT_SENSITIVITY(100) PORT_KEYDELTA(10) PORT_CENTERDELTA(0) PORT_PLAYER(5) PORT_CODE_DEC(JOYCODE_Y_DOWN_SWITCH) PORT_CODE_INC(JOYCODE_Y_UP_SWITCH)
PORT_START("AN3")
PORT_BIT(0xff, 0x00, IPT_POSITIONAL_V) PORT_NAME("Modulation Wheel") PORT_SENSITIVITY(100) PORT_KEYDELTA(10) PORT_CENTERDELTA(0) PORT_PLAYER(4) PORT_CODE_DEC(JOYCODE_Y_DOWN_SWITCH) PORT_CODE_INC(JOYCODE_Y_UP_SWITCH)
PORT_START("AN4")
PORT_BIT(0xff, 0x7f, IPT_PADDLE) PORT_NAME("Pitch Wheel") PORT_SENSITIVITY(100) PORT_KEYDELTA(10) PORT_MINMAX(0x00, 0xff) PORT_PLAYER(3) PORT_CODE_DEC(JOYCODE_Y_DOWN_SWITCH) PORT_CODE_INC(JOYCODE_Y_UP_SWITCH)
INPUT_PORTS_END
/**************************************************************************/
void fz1_state::maincpu_map(address_map &map)
{
map(0x00000, 0x0ffff).ram();
map(0x10000, 0x1ffff).rw(m_ram_bank, FUNC(address_map_bank_device::read16), FUNC(address_map_bank_device::write16));
map(0x80000, 0x8ffff).mirror(0x70000).rom().region("maincpu", 0);
}
/**************************************************************************/
void fz1_state::fz10m_io_map(address_map &map)
{
// 0x00-07: GAA
// 0x08-0f: GAB
map(0x10, 0x13).mirror(0x04).m("fdc", FUNC(upd72065_device::map)).umask16(0x00ff);
map(0x18, 0x1f).rw(m_io[0], FUNC(i8255_device::read), FUNC(i8255_device::write)).umask16(0x00ff);
map(0x20, 0x27).rw(m_io[1], FUNC(i8255_device::read), FUNC(i8255_device::write)).umask16(0x00ff);
map(0x60, 0x67).r(FUNC(fz1_state::adc_latch_r));
map(0x68, 0x6f).r(FUNC(fz1_state::adc_r)).umask16(0x00ff);
map(0x70, 0x77).w(FUNC(fz1_state::gal_w)).umask16(0x00ff);
map(0x78, 0x7f).w(FUNC(fz1_state::led_w)).umask16(0x00ff);
// 0x80-bf: DCF/DCA
}
/**************************************************************************/
void fz1_state::fz1_io_map(address_map &map)
{
fz10m_io_map(map);
map(0x28, 0x2f).r(FUNC(fz1_state::subcpu_r)).umask16(0x00ff);
}
/**************************************************************************/
void fz1_state::fz20m_io_map(address_map &map)
{
fz10m_io_map(map);
map(0x30, 0x3f).m("scsi:7:spc", FUNC(mb89352_device::map));
}
/**************************************************************************/
void fz1_state::subcpu_map(address_map &map)
{
map(0x00, 0xff).rw(m_kbd, FUNC(msm6200_device::read), FUNC(msm6200_device::write));
}
/**************************************************************************/
void fz1_state::fz10m(machine_config &config)
{
V50(config, m_maincpu, 16_MHz_XTAL);
m_maincpu->set_addrmap(AS_PROGRAM, &fz1_state::maincpu_map);
m_maincpu->set_addrmap(AS_IO, &fz1_state::fz10m_io_map);
m_maincpu->set_tclk(2_MHz_XTAL);
m_maincpu->tout2_cb().set_inputline(m_maincpu, INPUT_LINE_IRQ7);
midi_port_device &mdin(MIDI_PORT(config, "mdin", midiin_slot, "midiin"));
mdin.rxd_handler().set(m_maincpu, FUNC(v50_device::rxd_w));
MIDI_PORT(config, "mdout", midiout_slot, "midiout");
m_maincpu->txd_handler_cb().set("mdout", FUNC(midi_port_device::write_txd));
MIDI_PORT(config, "mdthru", midiout_slot, "midiout");
mdin.rxd_handler().append("mdthru", FUNC(midi_port_device::write_txd));
// RAM is fixed on FZ-10M/20M but expandable on FZ-1
RAM(config, m_ram).set_default_size("2M");
ADDRESS_MAP_BANK(config, m_ram_bank).set_options(ENDIANNESS_LITTLE, 16, 21, 0x10000);
I8255(config, m_io[0]);
// port A: parallel port data bus
m_io[0]->in_pb_callback().set_ioport("IO1_PB");
// port C: parallel port control
I8255(config, m_io[1]);
m_io[1]->out_pa_callback().set_ioport("IO2_PA");
m_io[1]->out_pb_callback().set_ioport("IO2_PB");
m_io[1]->in_pc_callback().set(FUNC(fz1_state::keys_r));
UPD72065(config, "fdc", 16_MHz_XTAL / 4);
HD44352(config, m_lcdc, 2_MHz_XTAL); // actually HD44350 + 2x HD44251
screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_LCD));
screen.set_refresh_hz(50);
screen.set_vblank_time(ATTOSECONDS_IN_USEC(2500)); /* not accurate */
screen.set_screen_update(m_lcdc, FUNC(hd44352_device::screen_update));
screen.set_size(96, 64);
screen.set_visarea(0, 96-1, 0, 64-1);
screen.set_palette("palette");
PALETTE(config, "palette", palette_device::MONOCHROME_INVERTED);
}
/**************************************************************************/
void fz1_state::fz1(machine_config &config)
{
fz10m(config);
m_maincpu->set_addrmap(AS_IO, &fz1_state::fz1_io_map);
// expansion slot on a stock unit only allows 2MB, but hardware and firmware support up to 4MB
m_ram->set_extra_options("1M,3M,4M");
m_ram_bank->set_addr_width(22);
I8049(config, m_subcpu, 8.96_MHz_XTAL);
m_subcpu->set_addrmap(AS_IO, &fz1_state::subcpu_map);
m_subcpu->p2_out_cb().set(FUNC(fz1_state::sub_p2_w));
m_subcpu->t0_in_cb().set(FUNC(fz1_state::sync49_r));
MSM6200(config, m_kbd, 2.47_MHz_XTAL);
m_kbd->irq_cb().set_inputline(m_subcpu, MCS48_INPUT_IRQ);
}
/**************************************************************************/
static void scsi_devices(device_slot_interface &device)
{
device.option_add("harddisk", NSCSI_HARDDISK);
device.option_add_internal("mb89352", MB89352);
}
/**************************************************************************/
void fz1_state::fz20m(machine_config &config)
{
fz10m(config);
m_maincpu->set_addrmap(AS_IO, &fz1_state::fz20m_io_map);
m_maincpu->in_ior_cb<1>().set("scsi:7:spc", FUNC(mb89352_device::dma_r));
m_maincpu->out_iow_cb<1>().set("scsi:7:spc", FUNC(mb89352_device::dma_w));
// note: loading from HD requires running "HDD Operater" [sic] from FL-D1 program disk
NSCSI_BUS(config, "scsi");
NSCSI_CONNECTOR(config, "scsi:0", scsi_devices, "harddisk");
NSCSI_CONNECTOR(config, "scsi:1", scsi_devices, nullptr);
NSCSI_CONNECTOR(config, "scsi:2", scsi_devices, nullptr);
NSCSI_CONNECTOR(config, "scsi:3", scsi_devices, nullptr);
NSCSI_CONNECTOR(config, "scsi:4", scsi_devices, nullptr);
NSCSI_CONNECTOR(config, "scsi:5", scsi_devices, nullptr);
NSCSI_CONNECTOR(config, "scsi:6", scsi_devices, nullptr);
NSCSI_CONNECTOR(config, "scsi:7").option_set("spc", MB89352).machine_config(
[this](device_t *device)
{
mb89352_device &spc = downcast<mb89352_device &>(*device);
spc.set_clock(8_MHz_XTAL);
spc.out_irq_callback().set_inputline(m_maincpu, INPUT_LINE_IRQ3);
spc.out_dreq_callback().set(m_maincpu, FUNC(v50_device::dreq_w<1>));
});
}
/**************************************************************************/
void fz1_state::machine_start()
{
m_led.resolve();
m_key_sel = 0;
m_adc_sel = 0;
m_adc_value = 0;
m_sub_p2 = 0;
m_ram_bank->space().install_ram(0, m_ram->mask(), m_ram->pointer());
save_item(NAME(m_key_sel));
save_item(NAME(m_adc_sel));
save_item(NAME(m_adc_value));
save_item(NAME(m_sub_p2));
save_item(NAME(m_lcd_ready));
save_item(NAME(m_lcd_nibble));
save_item(NAME(m_lcd_data));
save_item(NAME(m_lcd_data_phase));
}
/**************************************************************************/
void fz1_state::machine_reset()
{
m_lcd_ready = 1;
m_lcd_nibble = 0;
m_lcd_data = 0;
m_lcd_data_phase = 0;
}
/**************************************************************************/
u8 fz1_state::keys_r()
{
return m_keys[m_key_sel & 3]->read();
}
/**************************************************************************/
u8 fz1_state::adc_latch_r()
{
if (!machine().side_effects_disabled())
m_adc_value = m_analog[m_adc_sel & 7].read_safe(0);
return 0;
}
/**************************************************************************/
u8 fz1_state::subcpu_r()
{
if (!machine().side_effects_disabled())
{
m_sync49 = 0;
m_maincpu->set_input_line(INPUT_LINE_IRQ6, CLEAR_LINE);
}
return m_subcpu->p1_r();
}
/**************************************************************************/
void fz1_state::sub_p2_w(u8 data)
{
if (BIT(~data & m_sub_p2, 6))
m_maincpu->set_input_line(INPUT_LINE_IRQ6, ASSERT_LINE);
if (BIT(~data & m_sub_p2, 7))
m_sync49 = 1;
m_sub_p2 = data;
}
/**************************************************************************/
int fz1_state::cont49_r()
{
return BIT(m_sub_p2, 5);
}
/**************************************************************************/
void fz1_state::gal_w(u8 data)
{
m_lcd_ready = BIT(data, 7);
switch (data & 0x7f)
{
case 0x1f: // command start
m_lcdc->control_write(0x87);
m_lcd_data_phase = 0;
break;
case 0x10: // data start
m_lcdc->control_write(0x86);
m_lcd_data_phase = 1;
break;
default:
if (!m_lcd_ready)
{
if (!m_lcd_nibble)
{
if (!m_lcd_data_phase)
m_lcd_data = (data & 0xf);
else
m_lcd_data = (data << 4);
}
else
{
if (!m_lcd_data_phase)
m_lcd_data |= (data << 4);
else
m_lcd_data |= (data & 0xf);
m_lcdc->data_write(m_lcd_data);
}
m_lcd_nibble ^= 1;
}
}
}
/**************************************************************************/
void fz1_state::led_w(u8 data)
{
for (int i = 0; i < m_led.size(); i++)
m_led[i] = BIT(~data, i);
}
/**************************************************************************/
ROM_START( fz1 )
ROM_REGION(0x10000, "maincpu", 0) // "ROM ver.[B]"
ROM_LOAD16_BYTE( "fz1s.bin", 0x00000, 0x08000, CRC(b0ba313d) SHA1(45a3660d708f0a584f9f61d04e205a96688f0950) )
ROM_LOAD16_BYTE( "fz2s.bin", 0x00001, 0x08000, CRC(57098176) SHA1(ceeb4de4a3df35430497bee37ec73f1b12042729) )
ROM_REGION(0x800, "subcpu", 0) // this dump is actually uPD80C49HC-187 from the HT-6000, though it appears functionally identical
ROM_LOAD("upd8049hc-672.bin", 0x000, 0x800, BAD_DUMP CRC(47b47af7) SHA1(8f0515f95dcc6e224a8a59e0c2cd7ddb4796e34e))
ROM_REGION( 0x800, "lcdc", 0 ) // taken from pb1000, may not be completely identical
ROM_LOAD( "charset.bin", 0x000, 0x800, BAD_DUMP CRC(7f144716) SHA1(a02f1ecc6dc0ac55b94f00931d8f5cb6b9ffb7b4))
ROM_END
ROM_START( fz10m )
ROM_REGION(0x10000, "maincpu", 0) // "ROM ver.[B]"
ROM_LOAD16_BYTE( "mz1b.bin", 0x00000, 0x08000, CRC(3e16943a) SHA1(d754b60901f848b43ee256c2d3f1dfeee031d943) )
ROM_LOAD16_BYTE( "mz2b.bin", 0x00001, 0x08000, CRC(1db8400d) SHA1(01edf16839afdd78820d7a0f8a410882c54889a9) )
ROM_REGION( 0x800, "lcdc", 0 ) // taken from pb1000, may not be completely identical
ROM_LOAD( "charset.bin", 0x000, 0x800, BAD_DUMP CRC(7f144716) SHA1(a02f1ecc6dc0ac55b94f00931d8f5cb6b9ffb7b4))
ROM_END
ROM_START( fz20m )
ROM_REGION(0x10000, "maincpu", 0) // "ROM hdd.[C]"
ROM_LOAD16_BYTE( "fz20m_l.bin", 0x00000, 0x08000, CRC(e16c9ccf) SHA1(aa2c5fc0465cb6c9b0c7a7ab31606ad1703327ee) )
ROM_LOAD16_BYTE( "fz20m_h.bin", 0x00001, 0x08000, CRC(be272cad) SHA1(09d5c901e2f8905415789595a69e7d4166c0e2d2) )
ROM_REGION( 0x800, "lcdc", 0 ) // taken from pb1000, may not be completely identical
ROM_LOAD( "charset.bin", 0x000, 0x800, BAD_DUMP CRC(7f144716) SHA1(a02f1ecc6dc0ac55b94f00931d8f5cb6b9ffb7b4))
ROM_END
} // anonymous namespace
SYST( 1987, fz1, 0, 0, fz1, fz1, fz1_state, empty_init, "Casio", "FZ-1 Digital Sampling Synthesizer", MACHINE_NOT_WORKING | MACHINE_NO_SOUND )
SYST( 1987, fz10m, fz1, 0, fz10m, fz10m, fz1_state, empty_init, "Casio", "FZ-10M Digital Sampling Synthesizer Module", MACHINE_NOT_WORKING | MACHINE_NO_SOUND )
SYST( 1989, fz20m, fz1, 0, fz20m, fz10m, fz1_state, empty_init, "Casio", "FZ-20M Digital Sampling Synthesizer Module", MACHINE_NOT_WORKING | MACHINE_NO_SOUND )

View File

@ -16228,6 +16228,11 @@ fp1100
@source:casio/fp6000.cpp
fp6000
@source:casio/fz1.cpp
fz1
fz10m
fz20m
@source:casio/ht6000.cpp
ht6000