// license:MAME // copyright-holders:Dirk Best, Robbbert /****************************************************************************** Acorn System 1 (Microcomputer Kit) Skeleton driver Driver by Dirk Best 2011-06-26 Keyboard & display fixed. [Robbbert] http://speleotrove.com/acorn/ - (modify) Memory display and modification l (load) Reads a block of bytes from tape X (go) Run program starting at an address r (return) Resume after a breakpoint p (point) Inserts or removes breakpoint (up) Increment displayed address s (store) Writes a block of bytes to tape (down) Decrement displayed address Pasting: 0-F : as is (inc) : ^ (dec) : V M (memory) : - G (Go) : X Test Paste: -0100^11^22^33^44^55^66^77^88^99^-0100^ Now press up-arrow to confirm the data has been entered. Example usage: Turn on. Press -. Mode letter will show 'A'. Type in an address (example FE00). Press - (or any command key). Contents will show on the right. Use Up & Down keys to cycle through addresses. To save a tape, press S then enter start address, press S, enter end address+1, start recording and press S. The save only takes a few seconds. To load a tape, the display must just have dots, (reset if necessary), start playing tape and immediately press L. The last digit will flicker as the bytes load. At the end, the dots will show again. There's no error checking, so if it doesn't work, reset and try again. Note that left-most digit is not wired up, and therefore will always be blank. ******************************************************************************/ #include "emu.h" #include "cpu/m6502/m6502.h" #include "machine/ins8154.h" #include "machine/74145.h" #include "imagedev/cassette.h" #include "sound/wave.h" #include "acrnsys1.lh" class acrnsys1_state : public driver_device { public: acrnsys1_state(const machine_config &mconfig, device_type type, const char *tag) : driver_device(mconfig, type, tag), m_maincpu(*this, "maincpu"), m_ttl74145(*this, "ic8_7445"), m_cass(*this, "cassette"), m_digit(0) { } DECLARE_READ8_MEMBER(ins8154_b1_port_a_r); DECLARE_WRITE8_MEMBER(ins8154_b1_port_a_w); DECLARE_WRITE8_MEMBER(acrnsys1_led_segment_w); TIMER_DEVICE_CALLBACK_MEMBER(acrnsys1_c); TIMER_DEVICE_CALLBACK_MEMBER(acrnsys1_p); private: required_device m_maincpu; required_device m_ttl74145; required_device m_cass; UINT8 m_digit; UINT8 m_cass_data[4]; bool m_cass_state; }; /*************************************************************************** KEYBOARD HANDLING ***************************************************************************/ // bit 7 is cassin READ8_MEMBER( acrnsys1_state::ins8154_b1_port_a_r ) { UINT8 data = 0x7f, i, key_line = m_ttl74145->read(); for (i = 0; i < 8; i++) { if (BIT(key_line, i)) { char kbdrow[6]; sprintf(kbdrow,"X%X",i); data = (ioport(kbdrow)->read() & 0x38) | m_digit; break; } } data |= m_cass_data[2]; return data; } // bit 6 is cassout WRITE8_MEMBER( acrnsys1_state::ins8154_b1_port_a_w ) { m_digit = data & 0x47; m_ttl74145->write(m_digit & 7); m_cass_state = BIT(data, 6); } TIMER_DEVICE_CALLBACK_MEMBER(acrnsys1_state::acrnsys1_c) { m_cass_data[3]++; if (m_cass_state) m_cass->output(BIT(m_cass_data[3], 0) ? -1.0 : +1.0); // 2400Hz else m_cass->output(BIT(m_cass_data[3], 1) ? -1.0 : +1.0); // 1200Hz } TIMER_DEVICE_CALLBACK_MEMBER(acrnsys1_state::acrnsys1_p) { /* cassette - turn 1200/2400Hz to a bit */ m_cass_data[1]++; UINT8 cass_ws = (m_cass->input() > +0.03) ? 1 : 0; if (cass_ws != m_cass_data[0]) { m_cass_data[0] = cass_ws; m_cass_data[2] = ((m_cass_data[1] < 12) ? 128 : 0); m_cass_data[1] = 0; } } /*************************************************************************** LED DISPLAY ***************************************************************************/ WRITE8_MEMBER( acrnsys1_state::acrnsys1_led_segment_w ) { UINT8 key_line = m_ttl74145->read(); output_set_digit_value(key_line, data); } /*************************************************************************** ADDRESS MAPS ***************************************************************************/ static ADDRESS_MAP_START( acrnsys1_map, AS_PROGRAM, 8, acrnsys1_state ) AM_RANGE(0x0000, 0x03ff) AM_RAM AM_RANGE(0x0e00, 0x0e7f) AM_MIRROR(0x100) AM_DEVREADWRITE("b1", ins8154_device, ins8154_r, ins8154_w) AM_RANGE(0x0e80, 0x0eff) AM_MIRROR(0x100) AM_RAM AM_RANGE(0xf800, 0xf9ff) AM_MIRROR(0x600) AM_ROM ADDRESS_MAP_END /*************************************************************************** INPUT PORTS ***************************************************************************/ static INPUT_PORTS_START( acrnsys1 ) PORT_START("X0") PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("8") PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("M") PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-') PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("0") PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_BIT(0xc7, IP_ACTIVE_LOW, IPT_UNUSED) PORT_START("X1") PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("9") PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("G") PORT_CODE(KEYCODE_X) PORT_CHAR('X') PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("1") PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_BIT(0xc7, IP_ACTIVE_LOW, IPT_UNUSED) PORT_START("X2") PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("A") PORT_CODE(KEYCODE_A) PORT_CHAR('A') PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("P") PORT_CODE(KEYCODE_P) PORT_CHAR('P') PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("2") PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_BIT(0xc7, IP_ACTIVE_LOW, IPT_UNUSED) PORT_START("X3") PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("B") PORT_CODE(KEYCODE_B) PORT_CHAR('B') PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("S") PORT_CODE(KEYCODE_S) PORT_CHAR('S') PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("3") PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_BIT(0xc7, IP_ACTIVE_LOW, IPT_UNUSED) PORT_START("X4") PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("C") PORT_CODE(KEYCODE_C) PORT_CHAR('C') PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("L") PORT_CODE(KEYCODE_L) PORT_CHAR('L') PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("4") PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_BIT(0xc7, IP_ACTIVE_LOW, IPT_UNUSED) PORT_START("X5") PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("D") PORT_CODE(KEYCODE_D) PORT_CHAR('D') PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("R") PORT_CODE(KEYCODE_R) PORT_CHAR('R') PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("5") PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_BIT(0xc7, IP_ACTIVE_LOW, IPT_UNUSED) PORT_START("X6") PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("E") PORT_CODE(KEYCODE_E) PORT_CHAR('E') PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME(UTF8_UP) PORT_CODE(KEYCODE_UP) PORT_CHAR('^') PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("6") PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_BIT(0xc7, IP_ACTIVE_LOW, IPT_UNUSED) PORT_START("X7") PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F") PORT_CODE(KEYCODE_F) PORT_CHAR('F') PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME(UTF8_DOWN) PORT_CODE(KEYCODE_DOWN) PORT_CHAR('V') PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("7") PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_BIT(0xc7, IP_ACTIVE_LOW, IPT_UNUSED) PORT_START("reset") PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("RST") PORT_CODE(KEYCODE_F3) PORT_CHAR(UCHAR_MAMEKEY(F3)) PORT_BIT(0xfe, IP_ACTIVE_LOW, IPT_UNUSED) PORT_START("switch") PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Switch") PORT_CODE(KEYCODE_F1) PORT_CHAR(UCHAR_MAMEKEY(F1)) PORT_BIT(0xfe, IP_ACTIVE_LOW, IPT_UNUSED) PORT_START("config") PORT_CONFNAME( 0x03, 0x00, "Switch connected to") PORT_CONFSETTING( 0x00, "IRQ" ) PORT_CONFSETTING( 0x01, "NMI" ) PORT_CONFSETTING( 0x02, "RST" ) INPUT_PORTS_END /*************************************************************************** MACHINE DRIVERS ***************************************************************************/ static MACHINE_CONFIG_START( acrnsys1, acrnsys1_state ) /* basic machine hardware */ MCFG_CPU_ADD("maincpu", M6502, 1008000) /* 1.008 MHz */ MCFG_CPU_PROGRAM_MAP(acrnsys1_map) MCFG_DEFAULT_LAYOUT(layout_acrnsys1) /* sound hardware */ MCFG_SPEAKER_STANDARD_MONO("mono") MCFG_SOUND_WAVE_ADD(WAVE_TAG, "cassette") MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25) /* devices */ MCFG_DEVICE_ADD("b1", INS8154, 0) MCFG_INS8154_IN_A_CB(READ8(acrnsys1_state, ins8154_b1_port_a_r)) MCFG_INS8154_OUT_A_CB(WRITE8(acrnsys1_state, ins8154_b1_port_a_w)) MCFG_INS8154_OUT_B_CB(WRITE8(acrnsys1_state, acrnsys1_led_segment_w)) MCFG_DEVICE_ADD("ic8_7445", TTL74145, 0) MCFG_CASSETTE_ADD( "cassette", default_cassette_interface ) MCFG_TIMER_DRIVER_ADD_PERIODIC("acrnsys1_c", acrnsys1_state, acrnsys1_c, attotime::from_hz(4800)) MCFG_TIMER_DRIVER_ADD_PERIODIC("acrnsys1_p", acrnsys1_state, acrnsys1_p, attotime::from_hz(40000)) MACHINE_CONFIG_END /*************************************************************************** ROM DEFINITIONS ***************************************************************************/ ROM_START( acrnsys1 ) ROM_REGION(0x10000, "maincpu", 0) ROM_LOAD("acrnsys1.bin", 0xf800, 0x0200, CRC(43dcfc16) SHA1(b987354c55beb5e2ced761970c3339b895a8c09d)) ROM_END /*************************************************************************** GAME DRIVERS ***************************************************************************/ /* YEAR NAME PARENT COMPAT MACHINE INPUT INIT COMPANY FULLNAME FLAGS */ COMP( 1978, acrnsys1, 0, 0, acrnsys1, acrnsys1, driver_device, 0, "Acorn", "Acorn System 1", 0 )