Get Kurzweil K2000 skeleton driver to boot. (#9545)

This commit is contained in:
Peter Sobot 2022-04-21 08:23:46 -04:00 committed by GitHub
parent 0467f7c836
commit f7eec60e64
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -5,28 +5,38 @@
krz2000.cpp - Kurzweil K2000 series
Skeleton driver by R. Belmont
Additional improvements by Peter Sobot
Hardware in brief:
TMP68301 CPU @ 16 MHz
TMP68301 CPU @ 16 MHz (with debug port on RXD2/TXD2)
uPD72064 FDC
85C30 SCSI
M37450 on I/O board to handle panel/display/keyboard scanning
85C30 SCSI (53C80 on schematic?)
M37450 @ 10 MHz on I/O board to handle panel/display/keyboard scanning, LED control, LCD contrast, and the audio switching matrix
(16K of ROM stored on U69, 384 bytes of RAM, 8 A/D inputs, 2 D/A outputs, 6 ports of I/O, and a 31.25Kbaud serial link to the maincpu)
HD6303 on I/O board to manage reverb DSP program loading
VLSI ASIC "Calvin" - Unknown purpose (speculation: handles maincpu and PCM ROM/RAM addressing and DRAM refresh?)
VLSI ASIC "Calvin" - Handles maincpu and PCM ROM/RAM addressing, as well as resampling (and possibly DRAM refresh)
(on later K2000 and all later K-series units this is replaced by a more advanced VLSI ASIC "Janis")
2x VLSI ASIC "Hobbes" - Unknown purpose (speculation: 'reverb' DSP, interpolation, accumulation, and shifting and dithering down a wider accumulator to a 16 bit output sample?)
(service manual says "sample fetching tasks")
2x VLSI ASIC "Hobbes" - specialized DSP processors for sound synthesis (oscillators, filters, etc)
(service manual says "wave form generation and DSP functions")
(each Hobbes chip handles a subset of available voices, and seems independently programmable)
Digitech DSP256 Multi Effects VLSI Chip (reverb, chorus, delay, etc)
(EPROM seems avaialble on eBay, but the chip itself is quite custom)
***************************************************************************/
#include "emu.h"
#include "cpu/m68000/m68000.h"
#include "cpu/m6502/m3745x.h"
#include "machine/tmp68301.h"
#include "machine/bankdev.h"
#include "machine/upd765.h"
#include "machine/ncr5380.h"
#include "bus/nscsi/cd.h"
#include "bus/nscsi/hd.h"
#include "bus/midi/midi.h"
#include "video/t6963c.h"
#include "imagedev/floppy.h"
#include "screen.h"
#include "emupal.h"
#include "softlist.h"
@ -38,8 +48,11 @@ public:
k2000_state(const machine_config &mconfig, device_type type, const char *tag)
: driver_device(mconfig, type, tag)
, m_maincpu(*this, "maincpu")
// , m_scanner(*this, "scanner")
, m_1m_bank(*this, "bank1m")
, m_mainram(*this, "mainram")
// , m_midi(*this, "midi")
// , m_fdc(*this, "fdc")
{ }
void k2000(machine_config &config);
@ -52,24 +65,105 @@ private:
void bank_map_1m(address_map &map);
required_device<cpu_device> m_maincpu;
// required_device<cpu_device> m_scanner;
required_device<address_map_bank_device> m_1m_bank;
required_shared_ptr<uint16_t> m_mainram;
// optional_device<midi_port_device> m_midi;
// required_device<upd765a_device> m_fdc;
void ctrl_w(uint16_t data);
void swap_bit_ctrl_w(uint16_t data);
uint16_t battery_voltage_and_keyscanner_version(offs_t offset);
uint16_t calvin_read(offs_t offset);
void calvin_write(offs_t offset, uint16_t data);
uint16_t hobbes0_read(offs_t offset);
void hobbes0_write(offs_t offset, uint16_t data);
uint16_t hobbes1_read(offs_t offset);
void hobbes1_write(offs_t offset, uint16_t data);
void k2000_palette(palette_device &palette) const;
TIMER_CALLBACK_MEMBER(boot_hack_timer);
emu_timer *m_boot_hack_timer;
};
void k2000_state::ctrl_w(uint16_t data)
/**
* From the K2000/K2000R service manual:
*
* The 68301 processor's 16 megabits (sic) of address space are divided into 16 equal memory blocks,
* numbered 0-15. The first time the K2000 is powered up, Block 0 processes data for the boot
* EPROM and setup EPROM, while Block 1 processes data for the PSRAM. Many of the K2000's basic
* functions utilize the PSRAM, which accesses the higher address space of Block 1 in the CPU.
* This slows down the access time somewhat, since the address space of the CPU is accessed in
* sequence, beginning with Block 0.
*
* To optimize the processing speed, the K2000 performs a one-time software operation when
* powered up for the first time. The memory management unit (MMU) in the gate array logic chip
* (GAL) located at U35 on the engine board executes a "swap bit" function which makes Block 0
* of the CPU responsible for the PSRAM, and Block 1 responsible for the Boot EPROM and Setup
* EPROM. Consequently the PSRAM functions are processed as early as possible.
*
* Note this "16 equal memory blocks" idea is really just the top hex digit of the address -
* i.e.: 0x?FFFFF
*/
void k2000_state::swap_bit_ctrl_w(uint16_t data)
{
data &= 0xff;
logerror("%02x to ctrl_w\n", data);
// bit 4: 0=program ROM at 0, work RAM at 100000, 1=work RAM at 0, program ROM at 100000.
logerror("%02x written to swap_bit_ctrl_w\n", data);
// bit 4:
// 0 = program ROM at 0x000000, work RAM at 0x100000
// 1 = work RAM at 0x000000, program ROM at 0x100000
m_1m_bank->set_bank((data >> 4) & 1);
}
uint16_t k2000_state::battery_voltage_and_keyscanner_version(offs_t offset)
{
logerror("reading battery voltage and keyscanner version at %02x\n", offset);
uint8_t battery_voltage = 0x36;
uint8_t keyscanner_version = 0x12;
return (((uint16_t) battery_voltage) << 8) | ((uint16_t) keyscanner_version);
}
uint16_t k2000_state::calvin_read(offs_t offset)
{
logerror("Read from Calvin at %06x\n", offset);
return 0;
}
void k2000_state::calvin_write(offs_t offset, uint16_t data)
{
logerror("Write to Calvin at %06x = %04x\n", offset, data);
}
uint16_t k2000_state::hobbes0_read(offs_t offset)
{
logerror("Read from Hobbes[0] at %06x\n", offset);
return 0;
}
void k2000_state::hobbes0_write(offs_t offset, uint16_t data)
{
logerror("Write to Hobbes[0] at %06x = %04x\n", offset, data);
}
uint16_t k2000_state::hobbes1_read(offs_t offset)
{
logerror("Read from Hobbes[1] at %06x\n", offset);
return 0;
}
void k2000_state::hobbes1_write(offs_t offset, uint16_t data)
{
logerror("Write to Hobbes[1] at %06x = %04x\n", offset, data);
}
void k2000_state::machine_start()
{
m_boot_hack_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(k2000_state::boot_hack_timer), this));
m_boot_hack_timer->adjust(attotime::from_seconds(2), 0, attotime::never);
}
void k2000_state::machine_reset()
@ -77,23 +171,161 @@ void k2000_state::machine_reset()
m_1m_bank->set_bank(0);
}
TIMER_CALLBACK_MEMBER(k2000_state::boot_hack_timer)
{
logerror("Jumping to interrupt vector to continue boot sequence");
m_maincpu->set_pc(m_1m_bank->read32(0x80));
}
void k2000_state::k2000_map(address_map &map)
{
// word writes to 000000 region - unknown
// word writes to 000090 region - unknown
// word writes to 000180 region - unknown
// word writes to 000240 region - unknown
// The engine ROMs are mapped onto 0x0 when ENGROMCSb is low, which is IO3 of GODOT (pin 18)
// The setup ROMs are mapped onto 0x100000 when SUROMCSb is low, which is the IO2 output (pin 17) of GODOT
// This implies that IO3 of GODOT is low iff CA{20,23} are also low, and IO2 of GODOT is low iff CA{20,23} = 0x01
// Block 0, Block 1: ROM and RAM (depending on bank switch)
map(0x000000, 0x1fffff).m(m_1m_bank, FUNC(address_map_bank_device::amap16));
// Lots of writes to 0x372B68 -> 0x372C8C
// Block 4: PRAM?
// "The K2000 comes standard with 116KB, and with the PRAM upgrade, totals 760KB."
// Another source says:
// For the K2000 Series, the total memory allocated to all of these objects is
// 120K expandable to 760K with the PRAM option. For the K2500 Series, it is 256k,
// expandable to 1280k with the PRAM option. For the K2600 Series, it is 486k,
// expandable to 1506k with the PRAM option.
// These are pretty odd numbers - but it sounds like ~8KB of the RAM space is used
// for OS functions, meaning the built-in RAM might only be 128KB in total.
// The K2000 schematic shows 2x 1M "NVRAM" chips, one for the low byte, and one for
// the high byte, which means we should (?) actually have 2 * 1024 * 1024 / 8 = 262,144 bytes?
//
// The boot routines seem to write to 0x400000 and compare the value saved there, so
// this is probably the optional PRAM expansion.
map(0x400000, 0x400000 + ((2 * 1024 * 1024) / 8) - 1).ram();
// Init routine sets 0x4BAB44 -> 0x4BFFFA to 0x0000
// Reads from 0x4BFFFC and 0x4BFFFE seem to happen on startup.
// HOBBES0CSb = NAND(CS1', CA19) = high unless CS1 is high and CA19 is high
// HOBBES1CSb = NAND(CS1', !CA19) = high unless CS1 is high and CA19 is low
// 0xFFFC00 is the Address Decoder area that controls which part of memory causes CS1 to be "enabled" (low)
// At runtime,
// 0xFFFC00 = 0x50 =
// 0xFFFC01 = 0x3F
// 0xFFFC02 = 0x00
// 0xFFFC03 = 0x30
// For CS1:
// 0xFFFC04 = 0x60 = 0b0110 0000 = Start address of the memory area for CS1 = A21 + A22
// 0xFFFC05 = 0x3F = 0b0011 1111 = Size of memory area = M19 + M18 + M17 + M16 + M15-M9 + M8 = 1MB
// 0xFFFC06 = 0x00
// 0xFFFC07 = 0x30 = 0b0011 0000 = Area enabled, use external DTACK
// By this logic, Hobbes chips are mapped to 0x100000, 0x200000, 0x400000, 0x600000
// And their address mask is 0x000FFF00, which means the effective ranges are:
// 0x100???00
// Hobbes chip selection seems to look at CA19 and CS1
// Internal sample ROM is switched on SBA20,SBA21, which corresponds to CA21,CA22 (one bit off)
// meaning the internal address space for accessing the sample ROM is 0x200000 through 0x6fffff (?)
// Blocks 2, 3, 4, 5, 6
// map(0x200000, 0x2fffff).rom().region("pcm", 0); // Block 2: Sample ROM
// map(0x300000, 0x3fffff).rom().region("pcm", 0x100000); // Block 3: Sample ROM
// map(0x400000, 0x4fffff).rom().region("pcm", 0x200000); // Block 4: Sample ROM
// Writes to 0x4FFD82, 0x4FFD88, 0x4FFE24
// Hypothesis: Calvin (or Janis) is mapped at 0x500000
// Writes to 0x500402, 0x500418, 0x50041A early in the boot process
// Initialization then writes zeros in a descending ladder:
// 0x500400, 0x500402
// 0x5003FC, 0x5003FE, ...
// down to 0x500004 (then 0x500006)
// Calvin memory?
map(0x500000, 0x5003FF).rw(FUNC(k2000_state::calvin_read), FUNC(k2000_state::calvin_write));
// Calvin control registers?
map(0x500400, 0x5004FF).rw(FUNC(k2000_state::calvin_read), FUNC(k2000_state::calvin_write));
// Reads and writes to 0x580000
// Hobbes (it seems) is connected in the 0x600000 range
// The second Hobbes chip (?) seems connected at 0x680000
// Initialization seems to:
// - write to 0x600300, followed by 0x600xxx where xxx is in 0x400 through 0x5FF
// - write to 0x6?0002, 0x6?0006, 0x6?0004, through 0x6?000F4
// - write to 0x600004, 0x600014, 0x600024... through 0x6002F4
// (with a repeating pattern of [0x02, 0x00, 0x26, 0x24, 0x4A, 0x48])
// - write to 0x680004, 0x680014, 0x680024... through 0x6802F4
// (with a repeating pattern of [0x80, 0x02, 0xA4, 0x26, 0xC6, 0x4A])
// Each Hobbes chip seems to have two control registers, mapped at 0x600300/0x680300 and 0x600400/0x680400
// Hobbes memory?
map(0x600000, 0x6002FF).rw(FUNC(k2000_state::hobbes0_read), FUNC(k2000_state::hobbes0_write));
// Hobbes control registers?
map(0x600300, 0x6005FF).rw(FUNC(k2000_state::hobbes0_read), FUNC(k2000_state::hobbes0_write));
// Hobbes memory?
map(0x680000, 0x6802FF).rw(FUNC(k2000_state::hobbes1_read), FUNC(k2000_state::hobbes1_write));
// Hobbes control registers?
map(0x680300, 0x6805FF).rw(FUNC(k2000_state::hobbes1_read), FUNC(k2000_state::hobbes1_write));
// SROM - Setup ROM?
uint32 srom_base = 0x280000;
map(srom_base, srom_base + 0x40000 - 1).rom().region("maincpu", 0x100000);
// Calvin chip has a 20-bit address bus with A0 tied low and A12-15 tied high, giving it access to 0x?0??[0-E]
// Later models' Janis chips use 24-bit address buses (or at least they're all connected in the schematic)
// Hobbes has a 10-bit address bus with A0 tied low, giving access to 0x0 through 0x3FF
// Block 7: LCD control and bank switching
map(0x700000, 0x700003).rw("lcd", FUNC(lm24014h_device::read), FUNC(lm24014h_device::write)).umask16(0x00ff);
map(0x7e0000, 0x7e0001).w(FUNC(k2000_state::ctrl_w));
// Reads from 0x740000 (floppy?)
// Writes to 0x760000
// Writes to 0x7C0000
// Single byte reads seem to happen at 0x740000, which seems to be FDCCTLCSb?
// map(0x740000, 0x74000F).
map(0x7e0000, 0x7e0001).w(FUNC(k2000_state::swap_bit_ctrl_w));
// Some sort of hardware mapping - initial firmware boot expects a 4 at $78000B
map(0x780000, 0x78FFFF).ram();
// When (CPUASb + GODOT I6) and (GODOT I/O0 + IOCSb) are low,
// Address bits 17, 18, 19 get demultiplexed onto:
// 0, 0, 0 => LCDCSb
// 0, 0, 1 => FDCCSb
// 0, 1, 0 => FDCCTLCSb
// 0, 1, 1 => FDCOUTCSb
// 1, 0, 0 => SCSICSb
// 1, 0, 1 => SCSIDMACSb
// 1, 1, 0 => CPUEXPCSb
// 1, 1, 1 => MCTLREGCSb (OR'ed with WRITELOb to provide input into the Memory Management Control Register)
// map(0x800000, 0x8fffff); // Block 8: ???
// map(0x900000, 0x9fffff); // Block 9: ???
// map(0xa00000, 0xffffff); // Blocks 10, 11, 12, 13, 14: Orchestral ROM
// map(0x1000000, 0x18fffff); // Blocks 15, 16, 17, 18, 19: Contemporary ROM
}
void k2000_state::bank_map_1m(address_map &map)
{
map(0x000000, 0x0fffff).rom().region("maincpu", 0);
map(0x100000, 0x1fffff).ram().share("mainram");
// The "stride" of this bank map is 0x200000, so this is the second "view" of the same data
map(0x200000, 0x2fffff).ram().share("mainram");
map(0x300000, 0x3fffff).rom().region("maincpu", 0);
// Unsure if the battery voltage and keyscanner data is memory-mapped at these ranges (unlikely)
// or if this data is written to some time during the boot process. If it's the latter,
// this will have to change when loading different versions of the ROM (or someone has to figure
// out where the battery voltage is actually read from).
map(0x100000 + 0x1052, 0x100000 + 0x1053).r(FUNC(k2000_state::battery_voltage_and_keyscanner_version));
map(0x200000 + 0x1052, 0x200000 + 0x1053).r(FUNC(k2000_state::battery_voltage_and_keyscanner_version));
}
void k2000_state::k2000(machine_config &config)
@ -101,14 +333,47 @@ void k2000_state::k2000(machine_config &config)
TMP68301(config, m_maincpu, XTAL(12'000'000));
m_maincpu->set_addrmap(AS_PROGRAM, &k2000_state::k2000_map);
// MIDI_PORT(config, m_midi, midiin_slot, "midiin");
// TODO: Uncomment when the TMP68301 has serial/MIDI support, to wire up MIDI I/O and scanner.
// MIDI_PORT(config, m_midi, midiout_slot, "midiout");
// M37450(config, m_scanner, XTAL(10'000'000));
// The "Scanner" sub-CPU is connected to main CPU via:
// - MIDI_FM_ENG, going to P34/RxD, which comes from SERTxD, which is INTMIDITxD == TxD1
// - 37450_TXD, coming from P35/TxD, which is NAND'd together with 6303_TXD
// and inverted to provide SERRxD to the engine (maincpu), which goes to INTMIDIRxD
// eventually ending up at RxD1
// Essentially, the 68k's second built-in serial port runs at 31250Hz, which is MIDI baud rate,
// which is how it talks to the scanner to tell it to operate the LEDs on the front of the case.
// The external MIDI port(s) are connected directly to the 68K's first serial port, RxD0 and TxD0.
// (RxD2 and TxD2 are hooked up to a "debug port" which the manual says requires additional
// hardware - this is untested.)
// The scanner's ROM comes from an NTE2764 (U69, 28-pin DIP) EPROM of which 16Kb are used.
// (Note that on the K2500 and above, the scanner is an M37451M8-FP the ROM is 16KB, but stored on an M27256.)
// The scanner ROM from the K2500 may be compatible with the K2000, and can be pulled from "U2"
// on the K2500 Audio Scanner Board (Rev D)
ADDRESS_MAP_BANK(config, "bank1m").set_map(&k2000_state::bank_map_1m).set_options(ENDIANNESS_BIG, 16, 24, 0x200000);
// uPD765AC; clocked through SED9420C
// UPD765A(config, m_fdc, 16_MHz_XTAL / 4, true, true);
// m_fdc->intrq_wr_callback().set_inputline(m_maincpu, I6);
// FLOPPY_CONNECTOR(config, "fdc:0", dss1_floppies, "35dd", floppy_image_device::default_floppy_formats).enable_sound(true);
// FLOPPY_CONNECTOR(config, "fdc:1", dss1_floppies, nullptr, floppy_image_device::default_floppy_formats).enable_sound(true);
PALETTE(config, "palette", FUNC(k2000_state::k2000_palette), 2);
LM24014H(config, "lcd");
SPEAKER(config, "lspeaker").front_left();
SPEAKER(config, "rspeaker").front_right();
}
void k2000_state::k2000_palette(palette_device &palette) const
{
palette.set_pen_color(0, rgb_t(131, 136, 139));
palette.set_pen_color(1, rgb_t( 92, 83, 88));
}
static INPUT_PORTS_START( k2000 )
@ -199,7 +464,12 @@ ROM_START( k2000 )
ROM_REGION(0x3000, "pals", 0)
ROM_LOAD( "pseudo_v4d.u11.gal16v8b.jed", 0x000000, 0x000bd0, CRC(43561132) SHA1(a0c567c81022bc7fb83023d89556ccd5aa1ab36d) )
ROM_LOAD( "sndram_v1.u50.gal16v8b.jed", 0x001000, 0x000bd0, CRC(cabc9335) SHA1(968fa5baa43c7589c901f09b12085437834aeb37) )
// GODOT seems to take in the top 4 maincpu address lines (A20-A24) and multiplex/decode onto 11 (?) I/O lines
// Effectively takes care of the "memory block" logic (MMU/bank switching) that the service manual describes
ROM_LOAD( "godot_v5.u10.gal20v8a.jed", 0x002000, 0x00066f, CRC(c6517456) SHA1(b82530d46afdca5f6460e77ac11710cad55a6b89) )
// There's an additional GAL20V8 for the MMU - exact logic unknown, but the MCTL[0-3] lines are used, which seem
// like the "address space select" lines - so at least one or more of those address space areas map directly to SBA[22-25], which
// seem to be the Sample Bank address lines.
ROM_END
CONS( 1990, k2000, 0, 0, k2000, k2000, k2000_state, empty_init, "Kurzweil Music Systems", "K2000", MACHINE_NOT_WORKING|MACHINE_NO_SOUND )