// license:GPL-2.0+// copyright-holders:Juergen Buchmueller, Robbbert/****************************************************************************** Motorola Evaluation Kit 6800 D2 MEK6800D2 system driver Juergen Buchmueller, Jan 2000 2013-06-16 Working driver [Robbbert] memory map range short description 0000-00ff RAM 256 bytes RAM 0100-01ff RAM optional 256 bytes RAM 6000-63ff PROM optional PROM or 6000-67ff ROM optional ROM 8004-8007 PIA expansion port 8008-8009 ACIA cassette interface 8020-8023 PIA keyboard interface a000-a07f RAM 128 bytes RAM (JBUG scratch) c000-c3ff PROM optional PROM or c000-c7ff ROM optional ROM e000-e3ff ROM JBUG monitor program e400-ffff -/- mirrors of monitor romEnter the 4 digit address then the command key: - M : Examine and Change Memory (example: E000M, then G to skip to next, ESC to exit) - E : Escape (abort) operation (ESC key in our emulation) - R : Examine Registers - G : Begin execution at specified address - P : Punch data from memory to magnetic tape - L : Load memory from magnetic tape - N : Trace one instruction - V : Set (and remove) breakpointsThe keys are laid out as: P L N V 7 8 9 A M 4 5 6 B E 1 2 3 C R 0 F E D GPasting: 0-F : as is NEXT : ^ MEM : = GO : ^Test Paste: HA030=11^22^33^44^55^66^77^88^99^HA030= Now press up-arrow to confirm the data has been entered. If you wish to follow the tutorial in the manual, here is the test program that you need to enter in step 1: H0020=8E^00^FF^4F^C6^04^CE^00^10^AB^00^08^5A^26^FA^97^15^3F^H Save the above program to tape: HA002=00^20^00^32^HP (A002 has start address, A004 has end address, big endian)TODO Display should go blank during cassette operations******************************************************************************/#include"emu.h"#include"cpu/m6800/m6800.h"#include"imagedev/cassette.h"#include"imagedev/snapquik.h"#include"machine/6821pia.h"#include"machine/6850acia.h"#include"machine/clock.h"#include"machine/timer.h"#include"speaker.h"#include"mekd2.lh"#define XTAL_MEKD2 1228800classmekd2_state:publicdriver_device{public:enum{TIMER_TRACE};mekd2_state(constmachine_config&mconfig,device_typetype,constchar*tag):driver_device(mconfig,type,tag),m_maincpu(*this,"maincpu"),m_pia_s(*this,"pia_s"),m_pia_u(*this,"pia_u"),m_acia(*this,"acia"),m_cass(*this,"cassette"),m_digits(*this,"digit%u",0U){}voidmekd2(machine_config&config);private:DECLARE_READ_LINE_MEMBER(mekd2_key40_r);DECLARE_READ8_MEMBER(mekd2_key_r);DECLARE_WRITE_LINE_MEMBER(mekd2_nmi_w);DECLARE_WRITE8_MEMBER(mekd2_digit_w);DECLARE_WRITE8_MEMBER(mekd2_segment_w);DECLARE_QUICKLOAD_LOAD_MEMBER(quickload_cb);TIMER_DEVICE_CALLBACK_MEMBER(kansas_w);TIMER_DEVICE_CALLBACK_MEMBER(kansas_r);voidmekd2_mem(address_map&map);virtualvoiddevice_timer(emu_timer&timer,device_timer_idid,intparam,void*ptr)override;uint8_tm_cass_data[4];uint8_tm_segment;uint8_tm_digit;uint8_tm_keydata;boolm_cassbit;boolm_cassold;virtualvoidmachine_start()override;required_device<cpu_device>m_maincpu;required_device<pia6821_device>m_pia_s;required_device<pia6821_device>m_pia_u;required_device<acia6850_device>m_acia;required_device<cassette_image_device>m_cass;output_finder<6>m_digits;};/*********************************************************** Address Map************************************************************/voidmekd2_state::mekd2_mem(address_map&map){map(0x0000,0x00ff).ram();// user rammap(0x8004,0x8007).rw(m_pia_u,FUNC(pia6821_device::read),FUNC(pia6821_device::write));map(0x8008,0x8009).rw(m_acia,FUNC(acia6850_device::read),FUNC(acia6850_device::write));map(0x8020,0x8023).rw(m_pia_s,FUNC(pia6821_device::read),FUNC(pia6821_device::write));map(0xa000,0xa07f).ram();// system rammap(0xe000,0xe3ff).rom().mirror(0x1c00);/* JBUG ROM */}/*********************************************************** Keys************************************************************/staticINPUT_PORTS_START(mekd2)PORT_START("X0")PORT_BIT(0x01,IP_ACTIVE_LOW,IPT_KEYBOARD)PORT_NAME("0")PORT_CODE(KEYCODE_0)PORT_CHAR('0')PORT_BIT(0x02,IP_ACTIVE_LOW,IPT_KEYBOARD)PORT_NAME("F")PORT_CODE(KEYCODE_F)PORT_CHAR('F')PORT_BIT(0x04,IP_ACTIVE_LOW,IPT_KEYBOARD)PORT_NAME("E (hex)")PORT_CODE(KEYCODE_E)PORT_CHAR('E')PORT_BIT(0x08,IP_ACTIVE_LOW,IPT_KEYBOARD)PORT_NAME("D")PORT_CODE(KEYCODE_D)PORT_CHAR('D')PORT_START("X1")PORT_BIT(0x01,IP_ACTIVE_LOW,IPT_KEYBOARD)PORT_NAME("1")PORT_CODE(KEYCODE_1)PORT_CHAR('1')PORT_BIT(0x02,IP_ACTIVE_LOW,IPT_KEYBOARD)PORT_NAME("2")PORT_CODE(KEYCODE_2)PORT_CHAR('2')PORT_BIT(0x04,IP_ACTIVE_LOW,IPT_KEYBOARD)PORT_NAME("3")PORT_CODE(KEYCODE_3)PORT_CHAR('3')PORT_BIT(0x08,IP_ACTIVE_LOW,IPT_KEYBOARD)PORT_NAME("C")PORT_CODE(KEYCODE_C)PORT_CHAR('C')PORT_START("X2")PORT_BIT(0x01,IP_ACTIVE_LOW,IPT_KEYBOARD)PORT_NAME("4")PORT_CODE(KEYCODE_4)PORT_CHAR('4')PORT_BIT(0x02,IP_ACTIVE_LOW,IPT_KEYBOARD)PORT_NAME("5")PORT_CODE(KEYCODE_5)PORT_CHAR('5')PORT_BIT(0x04,IP_ACTIVE_LOW,IPT_KEYBOARD)PORT_NAME("6")PORT_CODE(KEYCODE_6)PORT_CHAR('6')PORT_BIT(0x08,IP_ACTIVE_LOW,IPT_KEYBOARD)PORT_NAME("B")PORT_CODE(KEYCODE_B)PORT_CHAR('B')PORT_START("X3")PORT_BIT(0x01,IP_ACTIVE_LOW,IPT_KEYBOARD)PORT_NAME("7")PORT_CODE(KEYCODE_7)PORT_CHAR('7')PORT_BIT(0x02,IP_ACTIVE_LOW,IPT_KEYBOARD)PORT_NAME("8")PORT_CODE(KEYCODE_8)PORT_CHAR('8')PORT_BIT(0x04,IP_ACTIVE_LOW,IPT_KEYBOARD)PORT_NAME("9")PORT_CODE(KEYCODE_9)PORT_CHAR('9')PORT_BIT(0x08,IP_ACTIVE_LOW,IPT_KEYBOARD)PORT_NAME("A")PORT_CODE(KEYCODE_A)PORT_CHAR('A')PORT_START("X4")PORT_BIT(0x01,IP_ACTIVE_LOW,IPT_KEYBOARD)PORT_NAME("P")PORT_CODE(KEYCODE_P)PORT_CHAR('P')// save tapePORT_BIT(0x02,IP_ACTIVE_LOW,IPT_KEYBOARD)PORT_NAME("L")PORT_CODE(KEYCODE_L)PORT_CHAR('L')// load tapePORT_BIT(0x04,IP_ACTIVE_LOW,IPT_KEYBOARD)PORT_NAME("N")PORT_CODE(KEYCODE_N)PORT_CHAR('N')// trace (step)PORT_BIT(0x08,IP_ACTIVE_LOW,IPT_KEYBOARD)PORT_NAME("V")PORT_CODE(KEYCODE_V)PORT_CHAR('V')// breakpointPORT_START("X5")PORT_BIT(0x01,IP_ACTIVE_LOW,IPT_KEYBOARD)PORT_NAME("M")PORT_CODE(KEYCODE_M)PORT_CHAR('=')// memoryPORT_BIT(0x02,IP_ACTIVE_LOW,IPT_KEYBOARD)PORT_NAME("E (escape)")PORT_CODE(KEYCODE_ESC)PORT_CHAR('H')PORT_BIT(0x04,IP_ACTIVE_LOW,IPT_KEYBOARD)PORT_NAME("R")PORT_CODE(KEYCODE_R)PORT_CHAR('R')// regsPORT_BIT(0x08,IP_ACTIVE_LOW,IPT_KEYBOARD)PORT_NAME("G")PORT_CODE(KEYCODE_G)PORT_CODE(KEYCODE_UP)PORT_CHAR('^')// go, nextINPUT_PORTS_END/*********************************************************** Trace hardware (what happens when N is pressed)************************************************************/voidmekd2_state::device_timer(emu_timer&timer,device_timer_idid,intparam,void*ptr){switch(id){caseTIMER_TRACE:m_maincpu->set_input_line(INPUT_LINE_NMI,ASSERT_LINE);break;default:assert_always(false,"Unknown id in mekd2_state::device_timer");}}WRITE_LINE_MEMBER(mekd2_state::mekd2_nmi_w){if(state)m_maincpu->set_input_line(INPUT_LINE_NMI,CLEAR_LINE);elsetimer_set(attotime::from_usec(18),TIMER_TRACE);}/*********************************************************** Keyboard************************************************************/READ_LINE_MEMBER(mekd2_state::mekd2_key40_r){returnBIT(m_keydata,6);}READ8_MEMBER(mekd2_state::mekd2_key_r){charkbdrow[4];uint8_ti;m_keydata=0xff;for(i=0;i<6;i++){if(BIT(m_digit,i)){sprintf(kbdrow,"X%d",i);m_keydata&=ioport(kbdrow)->read();}}i=0x80;if(m_digit<0x40)i=BIT(m_keydata,0)?0x80:0;elseif(m_digit<0x80)i=BIT(m_keydata,1)?0x80:0;elseif(m_digit<0xc0)i=BIT(m_keydata,2)?0x80:0;elsei=BIT(m_keydata,3)?0x80:0;returni|m_segment;}/*********************************************************** LED display************************************************************/WRITE8_MEMBER(mekd2_state::mekd2_segment_w){m_segment=data&0x7f;}WRITE8_MEMBER(mekd2_state::mekd2_digit_w){uint8_ti;if(data<0x3f){for(i=0;i<6;i++){if(BIT(data,i))m_digits[i]=~m_segment&0x7f;}}m_digit=data;}/*********************************************************** Interfaces************************************************************/QUICKLOAD_LOAD_MEMBER(mekd2_state::quickload_cb){staticconstcharmagic[]="MEK6800D2";charbuff[9];uint16_taddr,size;uint8_tident,*RAM=memregion("maincpu")->base();image.fread(buff,sizeof(buff));if(memcmp(buff,magic,sizeof(buff))){logerror("mekd2 rom load: magic '%s' not found\n",magic);returnimage_init_result::FAIL;}image.fread(&addr,2);addr=little_endianize_int16(addr);image.fread(&size,2);size=little_endianize_int16(size);image.fread(&ident,1);logerror("mekd2 rom load: $%04X $%04X $%02X\n",addr,size,ident);while(size-->0)image.fread(&RAM[addr++],1);returnimage_init_result::PASS;}TIMER_DEVICE_CALLBACK_MEMBER(mekd2_state::kansas_w){m_cass_data[3]++;if(m_cassbit!=m_cassold){m_cass_data[3]=0;m_cassold=m_cassbit;}if(m_cassbit)m_cass->output(BIT(m_cass_data[3],0)?-1.0:+1.0);// 2400Hzelsem_cass->output(BIT(m_cass_data[3],1)?-1.0:+1.0);// 1200Hz}TIMER_DEVICE_CALLBACK_MEMBER(mekd2_state::kansas_r){/* cassette - turn 1200/2400Hz to a bit */m_cass_data[1]++;uint8_tcass_ws=(m_cass->input()>+0.03)?1:0;if(cass_ws!=m_cass_data[0]){m_cass_data[0]=cass_ws;m_acia->write_rxd((m_cass_data[1]<12)?1:0);m_cass_data[1]=0;}}voidmekd2_state::machine_start(){m_digits.resolve();}/*********************************************************** Machine************************************************************/voidmekd2_state::mekd2(machine_config&config){/* basic machine hardware */M6800(config,m_maincpu,XTAL_MEKD2/2);/* 614.4 kHz */m_maincpu->set_addrmap(AS_PROGRAM,&mekd2_state::mekd2_mem);config.set_default_layout(layout_mekd2);/* sound hardware */SPEAKER(config,"mono").front_center();CASSETTE(config,m_cass);m_cass->add_route(ALL_OUTPUTS,"mono",0.05);/* Devices */PIA6821(config,m_pia_s,0);m_pia_s->readpa_handler().set(FUNC(mekd2_state::mekd2_key_r));m_pia_s->readcb1_handler().set(FUNC(mekd2_state::mekd2_key40_r));m_pia_s->writepa_handler().set(FUNC(mekd2_state::mekd2_segment_w));m_pia_s->writepb_handler().set(FUNC(mekd2_state::mekd2_digit_w));m_pia_s->ca2_handler().set(FUNC(mekd2_state::mekd2_nmi_w));m_pia_s->irqa_handler().set_inputline("maincpu",INPUT_LINE_NMI);m_pia_s->irqb_handler().set_inputline("maincpu",INPUT_LINE_NMI);PIA6821(config,m_pia_u,0);m_pia_u->irqa_handler().set_inputline("maincpu",M6800_IRQ_LINE);m_pia_u->irqb_handler().set_inputline("maincpu",M6800_IRQ_LINE);ACIA6850(config,m_acia,0);m_acia->txd_handler().set([this](boolstate){m_cassbit=state;});clock_device&acia_tx_clock(CLOCK(config,"acia_tx_clock",XTAL_MEKD2/256));// 4800Hzacia_tx_clock.signal_handler().set(m_acia,FUNC(acia6850_device::write_txc));clock_device&acia_rx_clock(CLOCK(config,"acia_rx_clock",300));// toggled by cassette circuitacia_rx_clock.signal_handler().set(m_acia,FUNC(acia6850_device::write_rxc));TIMER(config,"kansas_w").configure_periodic(FUNC(mekd2_state::kansas_w),attotime::from_hz(4800));TIMER(config,"kansas_r").configure_periodic(FUNC(mekd2_state::kansas_r),attotime::from_hz(40000));QUICKLOAD(config,"quickload","d2",attotime::from_seconds(1)).set_load_callback(FUNC(mekd2_state::quickload_cb),this);}/*********************************************************** ROMS************************************************************/ROM_START(mekd2)ROM_REGION(0x10000,"maincpu",0)ROM_LOAD("jbug.rom",0xe000,0x0400,CRC(5ed08792)SHA1(b06e74652a4c4e67c4a12ddc191ffb8c07f3332e))ROM_END/*************************************************************************** Game driver(s)***************************************************************************/// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGSCOMP(1977,mekd2,0,0,mekd2,mekd2,mekd2_state,empty_init,"Motorola","MEK6800D2",0)