MT 06756: nascom2, nascom1: Cassette records no signal

This commit is contained in:
Robbbert 2019-07-05 02:25:50 +10:00
parent 0b1cb00d02
commit c4c3f9978d

View File

@ -12,12 +12,15 @@ To Do:
- Nascom2 has two dipswitch banks, and a memory control header - Nascom2 has two dipswitch banks, and a memory control header
- Nascom3 (Gemini), nothing usable found - Nascom3 (Gemini), nothing usable found
Cassette: Cassette (nascom1):
It outputs a string of pulses at 1953.125Hz to indicate a 1, and blank tape for 0. This means that It outputs a string of pulses at 1953.125Hz to indicate a 1, and blank tape for 0. This means that
no tape will present a 0 to the UART instead of the expected 1 (idle). Part of the cassette no tape will present a 0 to the UART instead of the expected 1 (idle). Part of the cassette
schematic is missing, so a few liberties have been taken. The result is you can save a file and schematic is missing, so a few liberties have been taken. The result is you can save a file and
load it back. Haven't found wav files on the net to test with. load it back. Haven't found wav files on the net to test with.
Cassette (nascom2):
Standard Kansas City format, switchable (with a real switch) between 300 and 1200 baud.
*****************************************************************************************************/ *****************************************************************************************************/
#include "emu.h" #include "emu.h"
@ -31,7 +34,6 @@ Cassette:
#include "machine/z80pio.h" #include "machine/z80pio.h"
#include "machine/timer.h" #include "machine/timer.h"
#include "sound/wave.h"
#include "speaker.h" #include "speaker.h"
#include "bus/generic/slot.h" #include "bus/generic/slot.h"
@ -50,18 +52,18 @@ Cassette:
class nascom_state : public driver_device class nascom_state : public driver_device
{ {
public: public:
nascom_state(const machine_config &mconfig, device_type type, const char *tag) : nascom_state(const machine_config &mconfig, device_type type, const char *tag)
driver_device(mconfig, type, tag), : driver_device(mconfig, type, tag)
m_maincpu(*this, "maincpu"), , m_maincpu(*this, "maincpu")
m_ram(*this, RAM_TAG), , m_ram(*this, RAM_TAG)
m_hd6402(*this, "hd6402"), , m_hd6402(*this, "hd6402")
m_cass(*this, "cassette"), , m_cass(*this, "cassette")
m_screen(*this, "screen"), , m_screen(*this, "screen")
m_gfxdecode(*this, "gfxdecode"), , m_gfxdecode(*this, "gfxdecode")
m_palette(*this, "palette"), , m_palette(*this, "palette")
m_videoram(*this, "videoram"), , m_videoram(*this, "videoram")
m_gfx1_region(*this, "gfx1"), , m_gfx1_region(*this, "gfx1")
m_keyboard(*this, "KEY.%u", 0) , m_keyboard(*this, "KEY.%u", 0)
{ } { }
void nascom(machine_config &config); void nascom(machine_config &config);
@ -79,6 +81,8 @@ protected:
DECLARE_READ8_MEMBER(nascom1_port_01_r); DECLARE_READ8_MEMBER(nascom1_port_01_r);
DECLARE_WRITE8_MEMBER(nascom1_port_01_w); DECLARE_WRITE8_MEMBER(nascom1_port_01_w);
DECLARE_READ8_MEMBER(nascom1_port_02_r); DECLARE_READ8_MEMBER(nascom1_port_02_r);
DECLARE_READ_LINE_MEMBER(hd6402_si);
DECLARE_WRITE_LINE_MEMBER(hd6402_so);
void screen_update(bitmap_ind16 &bitmap, const rectangle &cliprect, int char_height); void screen_update(bitmap_ind16 &bitmap, const rectangle &cliprect, int char_height);
@ -91,20 +95,14 @@ protected:
required_memory_region m_gfx1_region; required_memory_region m_gfx1_region;
required_ioport_array<8> m_keyboard; required_ioport_array<8> m_keyboard;
private:
int m_tape_size; int m_tape_size;
uint8_t *m_tape_image; uint8_t *m_tape_image;
int m_tape_index; int m_tape_index;
uint8_t m_kb_select; uint8_t m_kb_select;
uint8_t m_kb_control; uint8_t m_kb_control;
bool m_cassinbit, m_cassoutbit, m_cassold; bool m_cassinbit, m_cassoutbit, m_cassold;
u16 m_cass_cnt[2];
u8 m_port00; u8 m_port00;
TIMER_DEVICE_CALLBACK_MEMBER(kansas_r);
DECLARE_READ_LINE_MEMBER(nascom1_hd6402_si);
DECLARE_WRITE_LINE_MEMBER(nascom1_hd6402_so);
DECLARE_WRITE_LINE_MEMBER(kansas_w);
DECLARE_DEVICE_IMAGE_LOAD_MEMBER( load_nascom1_cassette ); DECLARE_DEVICE_IMAGE_LOAD_MEMBER( load_nascom1_cassette );
DECLARE_DEVICE_IMAGE_UNLOAD_MEMBER( unload_nascom1_cassette ); DECLARE_DEVICE_IMAGE_UNLOAD_MEMBER( unload_nascom1_cassette );
template<int Dest> DECLARE_SNAPSHOT_LOAD_MEMBER( snapshot_cb ); template<int Dest> DECLARE_SNAPSHOT_LOAD_MEMBER( snapshot_cb );
@ -113,28 +111,31 @@ private:
class nascom1_state : public nascom_state class nascom1_state : public nascom_state
{ {
public: public:
nascom1_state(const machine_config &mconfig, device_type type, const char *tag) : nascom1_state(const machine_config &mconfig, device_type type, const char *tag)
nascom_state(mconfig, type, tag) : nascom_state(mconfig, type, tag)
{ } { }
void nascom1(machine_config &config); void nascom1(machine_config &config);
uint32_t screen_update_nascom(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); uint32_t screen_update_nascom(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
private: private:
void nascom1_io(address_map &map); void nascom1_io(address_map &map);
void nascom1_mem(address_map &map); void nascom1_mem(address_map &map);
TIMER_DEVICE_CALLBACK_MEMBER(nascom1_kansas_r);
DECLARE_WRITE_LINE_MEMBER(nascom1_kansas_w);
u16 m_cass_cnt[2];
}; };
class nascom2_state : public nascom_state class nascom2_state : public nascom_state
{ {
public: public:
nascom2_state(const machine_config &mconfig, device_type type, const char *tag) : nascom2_state(const machine_config &mconfig, device_type type, const char *tag)
nascom_state(mconfig, type, tag), : nascom_state(mconfig, type, tag)
m_nasbus(*this, NASBUS_TAG), , m_clock(*this, "uart_clock")
m_socket1(*this, "socket1"), , m_nasbus(*this, NASBUS_TAG)
m_socket2(*this, "socket2"), , m_socket1(*this, "socket1")
m_lsw1(*this, "lsw1") , m_socket2(*this, "socket2")
, m_lsw1(*this, "lsw1")
{ } { }
void nascom2(machine_config &config); void nascom2(machine_config &config);
@ -142,7 +143,12 @@ public:
void init_nascom2c(); void init_nascom2c();
DECLARE_INPUT_CHANGED_MEMBER(cass_speed);
private: private:
TIMER_DEVICE_CALLBACK_MEMBER(nascom2_kansas_r);
DECLARE_MACHINE_RESET(nascom2);
DECLARE_WRITE_LINE_MEMBER(nascom2_kansas_w);
DECLARE_WRITE_LINE_MEMBER(ram_disable_w); DECLARE_WRITE_LINE_MEMBER(ram_disable_w);
DECLARE_WRITE_LINE_MEMBER(ram_disable_cpm_w); DECLARE_WRITE_LINE_MEMBER(ram_disable_cpm_w);
uint32_t screen_update_nascom(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); uint32_t screen_update_nascom(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
@ -155,12 +161,13 @@ private:
void nascom2_mem(address_map &map); void nascom2_mem(address_map &map);
void nascom2c_mem(address_map &map); void nascom2c_mem(address_map &map);
virtual void machine_reset() override; required_device<clock_device> m_clock;
required_device<nasbus_device> m_nasbus; required_device<nasbus_device> m_nasbus;
required_device<generic_slot_device> m_socket1; required_device<generic_slot_device> m_socket1;
required_device<generic_slot_device> m_socket2; required_device<generic_slot_device> m_socket2;
required_ioport m_lsw1; required_ioport m_lsw1;
u8 m_cass_data[4];
bool m_cass_speed;
}; };
@ -221,17 +228,17 @@ READ8_MEMBER( nascom_state::nascom1_port_02_r )
return data; return data;
} }
READ_LINE_MEMBER( nascom_state::nascom1_hd6402_si ) READ_LINE_MEMBER( nascom_state::hd6402_si )
{ {
return m_cassinbit; return m_cassinbit;
} }
WRITE_LINE_MEMBER( nascom_state::nascom1_hd6402_so ) WRITE_LINE_MEMBER( nascom_state::hd6402_so )
{ {
m_cassoutbit = state; m_cassoutbit = state;
} }
WRITE_LINE_MEMBER( nascom_state::kansas_w ) WRITE_LINE_MEMBER( nascom1_state::nascom1_kansas_w )
{ {
// incoming 3906.25Hz // incoming 3906.25Hz
if (state) if (state)
@ -246,7 +253,7 @@ WRITE_LINE_MEMBER( nascom_state::kansas_w )
m_hd6402->write_tcp(state); m_hd6402->write_tcp(state);
} }
TIMER_DEVICE_CALLBACK_MEMBER( nascom_state::kansas_r ) TIMER_DEVICE_CALLBACK_MEMBER( nascom1_state::nascom1_kansas_r )
{ {
// cassette - pulses = 1; no pulses = 0 // cassette - pulses = 1; no pulses = 0
m_cass_cnt[1]++; m_cass_cnt[1]++;
@ -266,6 +273,45 @@ TIMER_DEVICE_CALLBACK_MEMBER( nascom_state::kansas_r )
} }
} }
WRITE_LINE_MEMBER( nascom2_state::nascom2_kansas_w )
{
// incoming @19230Hz
u8 twobit = m_cass_data[3] & 3;
if (state)
{
if (twobit == 0)
m_cassold = m_cassoutbit;
if (m_cassold)
m_cass->output(BIT(m_cass_data[3], 2) ? -1.0 : +1.0); // 2400Hz
else
m_cass->output(BIT(m_cass_data[3], 3) ? -1.0 : +1.0); // 1200Hz
m_cass_data[3]++;
}
if (m_cass_speed || !twobit)
{
m_hd6402->write_tcp(state);
m_hd6402->write_rcp(state);
}
}
TIMER_DEVICE_CALLBACK_MEMBER( nascom2_state::nascom2_kansas_r )
{
/* cassette - turn 1200/2400Hz to a bit */
m_cass_data[1]++;
uint8_t cass_ws = (m_cass->input() > +0.04) ? 1 : 0;
if (cass_ws != m_cass_data[0])
{
m_cass_data[0] = cass_ws;
m_cassinbit = (m_cass_data[1] < 12) ? 1 : 0;
m_cass_data[1] = 0;
}
}
// This stuff has never been connected up - what's it for? // This stuff has never been connected up - what's it for?
DEVICE_IMAGE_LOAD_MEMBER( nascom_state::load_nascom1_cassette ) DEVICE_IMAGE_LOAD_MEMBER( nascom_state::load_nascom1_cassette )
{ {
@ -413,6 +459,20 @@ void nascom_state::machine_reset()
m_hd6402->write_cs(1); m_hd6402->write_cs(1);
} }
MACHINE_RESET_MEMBER(nascom2_state, nascom2)
{
machine_reset();
// nascom2: restore speed at machine start
m_cass_speed = ioport("DSW0")->read();
// base machine reset
nascom_state::machine_reset();
// restart address (on the real system, a12 to a15 are forced to 1 for one memory cycle)
m_maincpu->set_state_int(Z80_PC, m_lsw1->read() << 12);
}
void nascom_state::init_nascom() void nascom_state::init_nascom()
{ {
// install extra memory // install extra memory
@ -422,14 +482,6 @@ void nascom_state::init_nascom()
} }
} }
void nascom2_state::machine_reset()
{
// base machine reset
nascom_state::machine_reset();
// restart address (on the real system, a12 to a15 are forced to 1 for one memory cycle)
m_maincpu->set_state_int(Z80_PC, m_lsw1->read() << 12);
}
// since we don't know for which regions we should disable ram, we just let other devices // since we don't know for which regions we should disable ram, we just let other devices
// overwrite the region they need, and re-install our ram when they are disabled // overwrite the region they need, and re-install our ram when they are disabled
@ -659,6 +711,11 @@ static INPUT_PORTS_START( nascom2 )
PORT_MODIFY("KEY.7") PORT_MODIFY("KEY.7")
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(']') PORT_CHAR('_') PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(']') PORT_CHAR('_')
PORT_START("DSW0")
PORT_DIPNAME(0x01, 0x00, "Cassette Baud Rate") PORT_CHANGED_MEMBER(DEVICE_SELF, nascom2_state, cass_speed, nullptr)
PORT_DIPSETTING(0x00, "300")
PORT_DIPSETTING(0x01, "1200")
// link switch on board // link switch on board
PORT_START("lsw1") PORT_START("lsw1")
PORT_DIPNAME(0x0f, 0x00, "Restart address") PORT_DIPNAME(0x0f, 0x00, "Restart address")
@ -705,6 +762,11 @@ static INPUT_PORTS_START( nascom2c )
PORT_DIPSETTING(0x0f, "F000H") PORT_DIPSETTING(0x0f, "F000H")
INPUT_PORTS_END INPUT_PORTS_END
INPUT_CHANGED_MEMBER(nascom2_state::cass_speed)
{
m_cass_speed = newval ? 1 : 0;
}
//************************************************************************** //**************************************************************************
// MACHINE DRIVERS // MACHINE DRIVERS
@ -724,29 +786,24 @@ void nascom_state::nascom(machine_config &config)
GFXDECODE(config, m_gfxdecode, m_palette, gfx_nascom1); GFXDECODE(config, m_gfxdecode, m_palette, gfx_nascom1);
PALETTE(config, m_palette, palette_device::MONOCHROME); PALETTE(config, m_palette, palette_device::MONOCHROME);
// pio
Z80PIO(config, "z80pio", 16_MHz_XTAL / 8);
// internal extra ram
RAM(config, m_ram).set_default_size("48K").set_extra_options("8K,16K,32K");
// uart // uart
AY31015(config, m_hd6402); AY31015(config, m_hd6402);
m_hd6402->read_si_callback().set(FUNC(nascom_state::nascom1_hd6402_si)); m_hd6402->read_si_callback().set(FUNC(nascom_state::hd6402_si));
m_hd6402->write_so_callback().set(FUNC(nascom_state::nascom1_hd6402_so)); m_hd6402->write_so_callback().set(FUNC(nascom_state::hd6402_so));
m_hd6402->set_auto_rdav(true); m_hd6402->set_auto_rdav(true);
clock_device &uart_clock(CLOCK(config, "uart_clock", (16_MHz_XTAL / 16) / 256));
uart_clock.signal_handler().set(FUNC(nascom_state::kansas_w));
uart_clock.signal_handler().append(m_hd6402, FUNC(ay31015_device::write_rcp));
// cassette is connected to the uart // cassette is connected to the uart
CASSETTE(config, m_cass); CASSETTE(config, m_cass);
m_cass->set_interface("nascom_cass"); m_cass->set_interface("nascom_cass");
m_cass->set_default_state(CASSETTE_STOPPED | CASSETTE_SPEAKER_ENABLED | CASSETTE_MOTOR_ENABLED); m_cass->set_default_state(CASSETTE_STOPPED | CASSETTE_SPEAKER_ENABLED | CASSETTE_MOTOR_ENABLED);
SPEAKER(config, "mono").front_center(); SPEAKER(config, "mono").front_center();
WAVE(config, "wave", m_cass).add_route(ALL_OUTPUTS, "mono", 0.05); m_cass->add_route(ALL_OUTPUTS, "mono", 0.05);
TIMER(config, "kansas_r").configure_periodic(FUNC(nascom_state::kansas_r), attotime::from_hz(40000));
// pio
Z80PIO(config, "z80pio", 16_MHz_XTAL / 8);
// internal extra ram
RAM(config, m_ram).set_default_size("48K").set_extra_options("8K,16K,32K");
// devices // devices
snapshot_image_device &snapshot(SNAPSHOT(config, "snapshot", "nas", attotime::from_msec(500))); snapshot_image_device &snapshot(SNAPSHOT(config, "snapshot", "nas", attotime::from_msec(500)));
@ -767,6 +824,11 @@ void nascom1_state::nascom1(machine_config &config)
// software // software
SOFTWARE_LIST(config, "snap_list").set_original("nascom_snap").set_filter("NASCOM1"); SOFTWARE_LIST(config, "snap_list").set_original("nascom_snap").set_filter("NASCOM1");
clock_device &uart_clock(CLOCK(config, "uart_clock", (16_MHz_XTAL / 16) / 256));
uart_clock.signal_handler().set(FUNC(nascom1_state::nascom1_kansas_w));
uart_clock.signal_handler().append(m_hd6402, FUNC(ay31015_device::write_rcp));
TIMER(config, "kansas_r").configure_periodic(FUNC(nascom1_state::nascom1_kansas_r), attotime::from_hz(40000));
} }
void nascom2_state::nascom2(machine_config &config) void nascom2_state::nascom2(machine_config &config)
@ -777,6 +839,8 @@ void nascom2_state::nascom2(machine_config &config)
m_maincpu->set_addrmap(AS_PROGRAM, &nascom2_state::nascom2_mem); m_maincpu->set_addrmap(AS_PROGRAM, &nascom2_state::nascom2_mem);
m_maincpu->set_addrmap(AS_IO, &nascom2_state::nascom2_io); m_maincpu->set_addrmap(AS_IO, &nascom2_state::nascom2_io);
MCFG_MACHINE_RESET_OVERRIDE(nascom2_state, nascom2 )
// video hardware // video hardware
m_screen->set_size(48 * 8, 16 * 14); m_screen->set_size(48 * 8, 16 * 14);
m_screen->set_visarea(0, 48 * 8 - 1, 0, 16 * 14 - 1); m_screen->set_visarea(0, 48 * 8 - 1, 0, 16 * 14 - 1);
@ -804,6 +868,10 @@ void nascom2_state::nascom2(machine_config &config)
SOFTWARE_LIST(config, "snap_list").set_original("nascom_snap").set_filter("NASCOM2"); SOFTWARE_LIST(config, "snap_list").set_original("nascom_snap").set_filter("NASCOM2");
SOFTWARE_LIST(config, "socket_list").set_original("nascom_socket"); SOFTWARE_LIST(config, "socket_list").set_original("nascom_socket");
SOFTWARE_LIST(config, "floppy_list").set_original("nascom_flop"); SOFTWARE_LIST(config, "floppy_list").set_original("nascom_flop");
CLOCK(config, m_clock, (16_MHz_XTAL / 32) / 26);
m_clock->signal_handler().set(FUNC(nascom2_state::nascom2_kansas_w));
TIMER(config, "kansas_r").configure_periodic(FUNC(nascom2_state::nascom2_kansas_r), attotime::from_hz(40000));
} }
void nascom2_state::nascom2c(machine_config &config) void nascom2_state::nascom2c(machine_config &config)