diff options
Diffstat (limited to 'src/mame/drivers/uchroma68.cpp')
-rw-r--r-- | src/mame/drivers/uchroma68.cpp | 497 |
1 files changed, 0 insertions, 497 deletions
diff --git a/src/mame/drivers/uchroma68.cpp b/src/mame/drivers/uchroma68.cpp deleted file mode 100644 index ca7eef4524e..00000000000 --- a/src/mame/drivers/uchroma68.cpp +++ /dev/null @@ -1,497 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders: 68bit -/****************************************************************************** - -Micro Chroma 68 -Motorola evaluation board for the MC6847 VDG and MC1372 RF modulator. - -The Micro Chroma was supplied as a kit that included the PCB and the major -parts and is reported to have been designed by the "applications group" in -Austin including Tim Ahrens, Jack Brown, and Hunter Scales. The micro Chroma -68 uses the TVBUG monitor which is a 2k monitor ROM that is included in the -MC6846 timer and is reported to have been written by John Dumas with parts -taken from MIKBUG with the help of Mike Wiles the author of MIKBUG. - -References: - -1. "Micro Chroma 68: The new 'bug' from Motorola TVBUG 1.2", Motorola - Semiconductor Products Inc. Microprocessor Operations., 1978 - -G - Go to user program. -G <addr> - Go to user program, starting at the given address 'addr'. -L - Load tape. The encoding uses the Kansas City Standard and the format is - largely JBUG compatible. Enter an offset, the difference between the - existing start address and the target start address. If the data can not be - stored in the memory then 'Memory Bad' is printed and it exits. The load - can be aborted by pressing the Escape key. -P - Punch tape. Enter the start address, the end address, a name up to 31 - characters long, and enter return to start. The format is largely JBUG - compatible, just avoid using 'B' or 'G' in the name. The punch can be - aborted by pressing the Escape key. -V - Verify Tape. Enter an offset, a difference between the existing start - address and the target start address. If there is an error then 'Memory - Bad' is printed and it exits. The verfiy can be aborted by pressing the - Escape key. -M <addr> - Memory examine and change at address 'addr'. - <hh><linefeed> - Enter new data for the address and increase the address. - If the memory can not be changed the 'Memory Bad' is printed that the - memory examine is exited. - '^' - decrease the address. - <carriage return> - exit the memory examine function. -E - Examine a memory block. Enter the start address, the end address, and then - a space to print the next line. -Q - Quick load. Enter the start address, the end address, then the hex bytes - to load separate by a space. -F - Fill memory. Enter the start address, the end address, and the fill byte. -O - Offset calculation. Enter the start address and then the end address. The - offset is printed as a 16 bit number, the lower 8 bits being the offset. - If the offset is too large then 'TOO FAR' is printed. - -R - Register display: CC B A X PC SP. The stack pointer (SP) is stored at - 0xf382 to 0xf383 and may be modifed via the memory examine 'M' function - there. The other registers are on the stack at: - SP + 1 : CC - SP + 2 : B - SP + 3 : A - SP + 4,5 : X - SP + 6,7 : P -Z - Clear screen. -S <addr> - Set a breakpoint at address 'addr'. Up to eight breakpoints may be - defined. A breakpoint can not be set at 0x0000. -U <addr> - Unset the breakpoint at address 'addr'. -D - Remove all breakpoints. -B - Print all breakpoints. -C - Contine user program, until next breakpoint. -N - Traces one instruction. -T <n> - Traces 'n' instructions. - -! - User defined code from 0xf396 to 0xf398, a jump instruction. -" - User defined code from 0xf399 to 0xf39a, a jump instruction. -# - User defined code from 0xf39c to 0xf39d, a jump instruction. - -A user input function can be defined at 0xf390 to 0xf392, which is room for a -jump instruction, and this is called by the monitor input loop. This function -should set the carry bit on return if there is user input. - -A user output function can be defined at 0xf393 to 0xf395 which is room for a -jump instruction. - -The board has a "Reset" button, and a "Break" button that toggled the NMI -line. TODO implement these. - -The documentation includes hardware suggestions for memory expansion. This -expands the RAM to use the address range 0x0000 to 0xcfff. - -The address range 0xe800 to 0xefff is for user expansion. The documentation -gives examples using this address range for two 1k or one 2k EPROM. - -The documentation includes position independent ROMable code for driving a -printer via the ACIA, and it also adds S19 'load', 'punch', and 'verify' tape -support for compatibility with MIKBUG, EXBUG, and MINIBUG. The documentation -suggests using this as an optional ROM at 0xe800 to 0xea73. The printer -support implements a user output function definable at 0xf393 to direct screen -output to the ACIA and with a hardware patch this can be directed to a RS232 -printer. The entry point for the printer support is 0xe800. The entry point -for the S19 support is 0xe802, so type 'G E802 <CR>' to enter this option and -it displays a choice of operations. It prints a 'B' for each record 'punched', -and a 'S' for each record loaded or verified, and it reports the address of -any bad memory. The S19 support writes a 0x11 (DC1) to start the tape playback -and a 0x12 (DC2) to start the tape recording as might be expected for the -Texas Instruments 733 ASR twin tape cassette terminal with automatic device -control, but it does not appear to issue DC3 or DC4 to turn the tape off. - -The documentation includes patches for a range or TSC software which is -generally supplied in Kansas City S19 format, so might need the above extra -EPROM support. The omission of any mention of support for Motorola software is -notable. - -The documentation includes instructions on using the Micro Chroma 68 as a dumb -terminal, requiring some minor hardware modifications to reuse the MC6850 ACIA -for a RS-232 interface, and it includes ROMable code at 0xfc00 to 0xffff code -to implement this, a substitute for the TVBUG monitor. TODO might consider -implementing this, but it was hardly a good terminal for the time. - -Address decoding was available in the range 0xc000 to 0xcfff in 1k blocks for -expansion. - -******************************************************************************/ - -#include "emu.h" -#include "cpu/m6800/m6800.h" -#include "machine/6821pia.h" -#include "machine/6850acia.h" -#include "machine/mc6846.h" -#include "machine/clock.h" -#include "machine/timer.h" -#include "video/mc6847.h" -#include "imagedev/cassette.h" -#include "sound/wave.h" -#include "speaker.h" - -#include "machine/terminal.h" -#include "video/mc6845.h" -#include "screen.h" - -#define XTAL_UCHROMA68 3.579545_MHz_XTAL - -class uchroma68_state : public driver_device -{ -public: - uchroma68_state(const machine_config &mconfig, device_type type, const char *tag) - : driver_device(mconfig, type, tag) - , m_maincpu(*this, "maincpu") - , m_mc6846(*this, "mc6846") - , m_mc6847(*this, "mc6847") - , m_pia(*this, "pia") - , m_acia(*this, "acia") - , m_acia_tx_clock(*this, "acia_tx_clock") - , m_screen(*this, "screen") - , m_video_ram(*this, "videoram") - , m_cass(*this, "cassette") - , m_semi_graphics_six_mod(*this, "SEMI_GRAPHICS_SIX_MOD") - { } - - void uchroma68(machine_config &config); - - enum - { - TIMER_KBD_STROBE - }; - -private: - required_device<cpu_device> m_maincpu; - required_device<mc6846_device> m_mc6846; - required_device<mc6847_ntsc_device> m_mc6847; - required_device<pia6821_device> m_pia; - required_device<acia6850_device> m_acia; - required_device<clock_device> m_acia_tx_clock; - required_device<screen_device> m_screen; - required_shared_ptr<uint8_t> m_video_ram; - required_device<cassette_image_device> m_cass; - required_ioport m_semi_graphics_six_mod; - - void uchroma68_mem(address_map &map); - virtual void machine_start() override; - virtual void machine_reset() override; - - virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override; - - uint8_t mc6847_videoram_r(offs_t offset); - uint8_t pia_pa_r(); - uint8_t pia_pb_r(); - void mc6846_out_w(uint8_t data); - void kbd_put(uint8_t data); - emu_timer *m_kbd_strobe_timer; - bool m_kbd_strobe; - uint8_t m_kbd_data; - bool m_video_inv; - - TIMER_DEVICE_CALLBACK_MEMBER(kansas_r); - DECLARE_WRITE_LINE_MEMBER(kansas_w); - uint8_t m_cass_rx_clock_count, m_cass_rx_period, m_cass_txcount; - bool m_cass_in, m_cass_inbit, m_cass_txbit, m_cass_last_txbit; -}; - - -/*********************************************************** - - Address Map - -************************************************************/ - -void uchroma68_state::uchroma68_mem(address_map &map) -{ - // On board user RAM - map(0x0000, 0x1fff).ram(); - - // Off board RAM expansion, as documented. - map(0x2000, 0xcfff).ram(); - - // Display RAM - map(0xd000, 0xe7ff).ram().share(m_video_ram); - - // Optional EPROM, with the supplied S19 tape format support. - map(0xe800, 0xebff).rom(); - - // Stack RAM - map(0xf000, 0xf3ff).ram(); - - map(0xf408, 0xf409).mirror(0x03b0).rw(m_acia, FUNC(acia6850_device::read), FUNC(acia6850_device::write)); - - map(0xf404, 0xf407).mirror(0x03b0).rw(m_pia, FUNC(pia6821_device::read), FUNC(pia6821_device::write)); - - // Programmable counter/timer and I/O. - map(0xf440, 0xf447).mirror(0x0380).rw(m_mc6846, FUNC(mc6846_device::read), FUNC(mc6846_device::write)); - - // TVBUG 1.2 ROM - map(0xf800, 0xffff).rom(); -} - -/*********************************************************** - - Keys - -************************************************************/ - -static INPUT_PORTS_START(uchroma68) - - // The documentation notes a hardware modification to allow the use of - // the Semi-graphics 6 mode of the MC6847. - PORT_START("SEMI_GRAPHICS_SIX_MOD") - PORT_CONFNAME(0x01, 0x00, "Semi-graphics 6 mode modification") - PORT_CONFSETTING(0x00, "No") - PORT_CONFSETTING(0x01, "Yes") - -INPUT_PORTS_END - - -/*********************************************************** - -************************************************************/ - -void uchroma68_state::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) -{ - switch (id) - { - case TIMER_KBD_STROBE: - m_kbd_strobe = 1; - m_kbd_data = 0; - break; - default: - throw emu_fatalerror("Unknown id in uchroma68_state::device_timer"); - } -} - -void uchroma68_state::mc6846_out_w(uint8_t data) -{ - m_mc6847->css_w(!BIT(data, 0)); - m_mc6847->intext_w(!BIT(data, 1)); - m_mc6847->ag_w(!BIT(data, 2)); - m_mc6847->gm0_w(BIT(data, 3)); - m_mc6847->gm1_w(BIT(data, 4)); - m_mc6847->gm2_w(BIT(data, 5)); - m_video_inv = BIT(data, 6); - // P7 is NC. -} - - -uint8_t uchroma68_state::mc6847_videoram_r(offs_t offset) -{ - offset &= 0x1fff; - if (offset > 0x17ff) return 0xff; - - uint8_t code = m_video_ram[offset]; - - if (m_semi_graphics_six_mod->read()) - m_mc6847->inv_w(m_video_inv); - else - m_mc6847->inv_w(m_video_inv | BIT(code, 6)); - - m_mc6847->as_w(BIT(code, 7)); - - return code; -} - -// TVBUG polls the parallel keyboard strobe every four video frames - it -// blinks the cursor for four frames between polling. At a 60Hz frame rate -// that gives polling at about every 67ms. A 70ms keyboard strobe period -// appears to be more than adequate. -void uchroma68_state::kbd_put(uint8_t data) -{ - m_kbd_data = data; - m_kbd_strobe_timer->adjust(attotime::from_msec(70)); - m_kbd_strobe = 0; -} - -uint8_t uchroma68_state::pia_pa_r() -{ - uint8_t data = m_kbd_data; - return (m_kbd_strobe << 7) | data; -} - -uint8_t uchroma68_state::pia_pb_r() -{ - // PB0 to PB4 are Up, Down, Left, Right, Home. - // PB5 is NC - // PB6 is V VDG - // PB7 is H VDG - return (m_mc6847->hs_r() << 7) | (m_mc6847->fs_r() << 6); -} - - -TIMER_DEVICE_CALLBACK_MEMBER(uchroma68_state::kansas_r) -{ - // Turn 1200/2400Hz to a bit - uint8_t cassin = (m_cass->input() > +0.04) ? 1 : 0; - uint8_t inbit = m_cass_inbit; - - m_cass_rx_period++; - - // The RX clock is recovered from the input data, and synchronized to - // the bit transitions. The software expects a 1x RX clock. - if (++m_cass_rx_clock_count > 133) - m_cass_rx_clock_count = 0; - - if (cassin != m_cass_in) - { - // A transition, so now check the period. - inbit = (m_cass_rx_period < 12) ? 1 : 0; - m_cass_in = cassin; - m_cass_rx_period = 0; - } - else if (m_cass_rx_period > 32) - { - // Idle the ACIA if there is no data. - m_cass_rx_period = 32; - inbit = 1; - } - - if (inbit != m_cass_inbit) - { - m_acia->write_rxd(inbit); - m_cass_inbit = inbit; - // Sync the RX clock with the data edges. - m_cass_rx_clock_count = 0; - } - - if (m_cass_rx_clock_count == 0) - m_acia->write_rxc(0); - else if (m_cass_rx_clock_count == 67) - m_acia->write_rxc(1); -} - -WRITE_LINE_MEMBER(uchroma68_state::kansas_w) -{ - // The Kansas City cassette format encodes a '0' bit by four cycles of - // a 1200 Hz sine wave, and a '1' bit as eight cycles of 2400 Hz, - // giving a 300 baud rate. - // - // The clock rate to the ACIA is 16x the baud rate, or 4800Hz, and is - // divided by 2 to get the 2400 Hz rate, or divided by 4 to get the - // 1200 Hz rate. - - // Sync the period phase on TX bit transitions. - if (m_cass_txbit != m_cass_last_txbit) - { - m_cass_txcount = 0; - m_cass_last_txbit = m_cass_txbit; - } - - if (m_cass_txbit) - m_cass->output(BIT(m_cass_txcount, 1) ? +1.0 : -1.0); // 2400Hz - else - m_cass->output(BIT(m_cass_txcount, 2) ? +1.0 : -1.0); // 1200Hz - - m_cass_txcount++; - m_acia->write_txc(state); -} - -void uchroma68_state::machine_start() -{ - m_kbd_strobe_timer = timer_alloc(TIMER_KBD_STROBE); - m_kbd_strobe = 1; - - save_item(NAME(m_kbd_strobe)); - save_item(NAME(m_kbd_data)); - save_item(NAME(m_video_inv)); - save_item(NAME(m_cass_rx_clock_count)); - save_item(NAME(m_cass_rx_period)); - save_item(NAME(m_cass_txcount)); - save_item(NAME(m_cass_in)); - save_item(NAME(m_cass_inbit)); - save_item(NAME(m_cass_txbit)); - save_item(NAME(m_cass_last_txbit)); -} - -void uchroma68_state::machine_reset() -{ - m_mc6846->reset(); - m_pia->reset(); - m_kbd_strobe_timer->reset(); - m_kbd_strobe = 1; - m_kbd_data = 0; - - // These MC6846 I/O outputs are pulled high. The high impedance state - // of these lines is not yet emulated by the mc6846 driver, and TVBUG - // does not drive them. On reset these are high impedance anyway, and - // pulled high, so their lines going to the VDG are initialized - // here. The first three lines are inverted. - m_mc6847->css_w(0); - m_mc6847->intext_w(0); - m_mc6847->ag_w(0); - m_mc6847->gm0_w(1); - m_mc6847->gm1_w(1); - m_mc6847->gm2_w(1); - m_video_inv = 1; - - m_cass_rx_clock_count = 0; - m_cass_rx_period = 0; - m_cass_txcount = 0; - m_cass_in = 0; - m_cass_inbit = 0; - m_cass_txbit = 0; - m_cass_last_txbit = 0; -} - -/*********************************************************** - - Machine - -************************************************************/ - -void uchroma68_state::uchroma68(machine_config &config) -{ - M6808(config, m_maincpu, XTAL_UCHROMA68); // 894.8 kHz clock - m_maincpu->set_addrmap(AS_PROGRAM, &uchroma68_state::uchroma68_mem); - - MC6846(config, m_mc6846, XTAL_UCHROMA68 / 4); // Same as the cpu clock - m_mc6846->out_port().set(FUNC(uchroma68_state::mc6846_out_w)); - - SPEAKER(config, "mono").front_center(); - - CASSETTE(config, m_cass); - m_cass->set_default_state(CASSETTE_STOPPED | CASSETTE_MOTOR_ENABLED | CASSETTE_SPEAKER_ENABLED); - m_cass->add_route(ALL_OUTPUTS, "mono", 0.05); - - SCREEN(config, m_screen, SCREEN_TYPE_RASTER); - - MC6847_NTSC(config, m_mc6847, XTAL_UCHROMA68); - m_mc6847->set_screen(m_screen); - m_mc6847->input_callback().set(FUNC(uchroma68_state::mc6847_videoram_r)); - - PIA6821(config, m_pia, 0); - m_pia->readpa_handler().set(FUNC(uchroma68_state::pia_pa_r)); - m_pia->readpb_handler().set(FUNC(uchroma68_state::pia_pb_r)); - - ACIA6850(config, m_acia, 0); - m_acia->txd_handler().set([this] (bool state) { m_cass_txbit = state; }); - - CLOCK(config, m_acia_tx_clock, 4800); - m_acia_tx_clock->signal_handler().set(FUNC(uchroma68_state::kansas_w)); - - TIMER(config, "kansas_r").configure_periodic(FUNC(uchroma68_state::kansas_r), attotime::from_hz(40000)); - - generic_keyboard_device &keyboard(GENERIC_KEYBOARD(config, "keyboard", 0)); - keyboard.set_keyboard_callback(FUNC(uchroma68_state::kbd_put)); -} - -/*********************************************************** - - ROMS - -************************************************************/ - -ROM_START(uchroma68) - ROM_REGION(0x10000,"maincpu",0) - ROM_LOAD("tvbug.rom", 0xf800, 0x0800, CRC(47f721e4) SHA1(31ea8d596f1f99ee26c4bea694245448bfdc3ee6)) - ROM_LOAD("uch68s19.rom", 0xe800, 0x0400, CRC(8932484f) SHA1(231098ab10185d400032415cf9b7273d736d3b87)) -ROM_END - -/*************************************************************************** - - Game driver(s) - -***************************************************************************/ - -// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS -COMP( 1980, uchroma68, 0, 0, uchroma68, uchroma68, uchroma68_state, empty_init, "Motorola", "Micro Chroma 68" , MACHINE_NO_SOUND_HW ) |