diff options
Diffstat (limited to 'src/mame/ausnz/eacc.cpp')
-rw-r--r-- | src/mame/ausnz/eacc.cpp | 306 |
1 files changed, 306 insertions, 0 deletions
diff --git a/src/mame/ausnz/eacc.cpp b/src/mame/ausnz/eacc.cpp new file mode 100644 index 00000000000..5705d6dd8d2 --- /dev/null +++ b/src/mame/ausnz/eacc.cpp @@ -0,0 +1,306 @@ +// license:BSD-3-Clause +// copyright-holders:Robbbert +/****************************************************************************** +* +* EA Car Computer +* by Robbbert, March 2011. +* +* Described in Electronics Australia magazine during 1982. +* Construction and usage: http://messui.polygonal-moogle.com/comp/eacc.pdf +* +* The only RAM is the 128 bytes that comes inside the CPU. +* +* This computer is mounted in a car, and various sensors (fuel flow, etc) +* are connected up. By pressing the appropriate buttons various statistics +* may be obtained. +* +* Memory Map +* 0000-007F internal ram +* 4000-7FFF ROM +* 8000-BFFF 6821 +* C000-FFFF ROM (mirror) +* +* The ROM was typed in twice from the dump in the magazine article, and the +* results compared. Only one byte was different, so I can be confident that +* it has been typed in properly. +* +* Setting up: You need to enter the number of expected pulses from the fuel +* and distance sensors. Paste this: 5 6M123N 7M400N (start, set litres cal to +* 123 pulses. set km cal to 400 pulses). Then paste this: 1950M0N 1845M0N (set +* petrol tank capacity to 50 litres, set current amount of petrol to 45). +* Now enter: 28M100N (the journey is 100km). Press 5 to start the journey. +* All settings are saved in nvram. +* +* Stats you can see while travelling: +* 0 - time elapsed +* 08 - time remaining +* 1 - fuel used +* 18 - fuel left +* 2 - km travelled +* 28 - km remaining +* 29 - km that could be travelled with the fuel you have left +* 3 - speed now +* 39 - average speed +* 4 - fuel consumption now (litres per 100km) +* 49 - fuel average consumption +* +******************************************************************************/ + +/* Core includes */ +#include "emu.h" +#include "cpu/m6800/m6800.h" +#include "eacc.lh" +#include "machine/6821pia.h" +#include "machine/7474.h" +#include "machine/clock.h" +#include "machine/nvram.h" + + +namespace { + +class eacc_state : public driver_device +{ +public: + eacc_state(const machine_config &mconfig, device_type type, const char *tag) + : driver_device(mconfig, type, tag) + , m_maincpu(*this, "maincpu") + , m_pia(*this, "pia") + , m_p_nvram(*this, "nvram") + , m_7474(*this, "7474") + , m_io_keyboard(*this, "X%u", 0U) + , m_digits(*this, "digit%u", 0U) + , m_leds(*this, "led%u", 0U) + { } + + void eacc(machine_config &config); + +protected: + virtual void machine_reset() override ATTR_COLD; + virtual void machine_start() override ATTR_COLD; + +private: + void scan_w(int state); + void cb2_w(int state); + void inputs_w(int state); + uint8_t keyboard_r(); + void digit_w(uint8_t data); + void segment_w(uint8_t data); + void mem_map(address_map &map) ATTR_COLD; + void do_nmi(bool, bool); + uint8_t m_digit = 0U; + bool m_cb2 = false; + bool m_scan = false; + bool m_disp = false; + + required_device<m6802_cpu_device> m_maincpu; + required_device<pia6821_device> m_pia; + required_shared_ptr<uint8_t> m_p_nvram; + required_device<ttl7474_device> m_7474; + required_ioport_array<4> m_io_keyboard; + output_finder<7> m_digits; + output_finder<8> m_leds; +}; + + + + +/****************************************************************************** + Address Maps +******************************************************************************/ + +void eacc_state::mem_map(address_map &map) +{ + map.unmap_value_high(); + map.global_mask(0xc7ff); // A11,A12,A13 not connected + map(0x0000, 0x001f).ram().share("nvram"); // inside cpu, battery-backed + map(0x0020, 0x007f).ram(); // inside cpu + map(0x4000, 0x47ff).rom().mirror(0x8000).region("maincpu",0); + map(0x8000, 0x8003).mirror(0x7fc).rw(m_pia, FUNC(pia6821_device::read), FUNC(pia6821_device::write)); +} + + +/****************************************************************************** + Input Ports +******************************************************************************/ + +static INPUT_PORTS_START(eacc) + PORT_START("X0") + PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("6 Litres Cal") PORT_CODE(KEYCODE_6_PAD) PORT_CHAR('6') + PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("ENTER") PORT_CODE(KEYCODE_ENTER_PAD) PORT_CHAR('M') + PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("2 km") PORT_CODE(KEYCODE_2_PAD) PORT_CHAR('2') + PORT_BIT( 0xf8, 0, IPT_UNUSED ) + + PORT_START("X1") + PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("5 START") PORT_CODE(KEYCODE_5_PAD) PORT_CHAR('5') + PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("END") PORT_CODE(KEYCODE_PLUS_PAD) PORT_CHAR('N') + PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("3 km/h") PORT_CODE(KEYCODE_3_PAD) PORT_CHAR('3') + PORT_BIT( 0xf8, 0, IPT_UNUSED ) + + PORT_START("X2") + PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("7 Km Cal") PORT_CODE(KEYCODE_7_PAD) PORT_CHAR('7') + PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("0 hour.min") PORT_CODE(KEYCODE_0_PAD) PORT_CHAR('0') + PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("4 l/100km") PORT_CODE(KEYCODE_4_PAD) PORT_CHAR('4') + PORT_BIT( 0xf8, 0, IPT_UNUSED ) + + PORT_START("X3") + PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("8 REM") PORT_CODE(KEYCODE_8_PAD) PORT_CHAR('8') + PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("1 litres") PORT_CODE(KEYCODE_1_PAD) PORT_CHAR('1') + PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("9 AV") PORT_CODE(KEYCODE_9_PAD) PORT_CHAR('9') + PORT_BIT( 0xf8, 0, IPT_UNUSED ) +INPUT_PORTS_END + +void eacc_state::machine_reset() +{ + m_cb2 = false; // pia is supposed to set this low at reset + m_digit = 0; +} + +void eacc_state::machine_start() +{ + m_digits.resolve(); + m_leds.resolve(); + + save_item(NAME(m_cb2)); + save_item(NAME(m_scan)); + save_item(NAME(m_digit)); + save_item(NAME(m_disp)); +} + +void eacc_state::inputs_w(int state) +{ + if (state) + m_pia->ca1_w(machine().rand() & 1); // movement + else + m_pia->ca2_w(machine().rand() & 1); // fuel usage +} + +void eacc_state::do_nmi(bool in_scan, bool in_cb2) +{ + if (in_scan && in_cb2) + { + m_maincpu->set_input_line(INPUT_LINE_NMI, ASSERT_LINE); + m_7474->clock_w(0); + } + else + { + m_maincpu->set_input_line(INPUT_LINE_NMI, CLEAR_LINE); + m_7474->clock_w(1); + } +} + +void eacc_state::cb2_w(int state) +{ + m_cb2 = state ? 1 : 0; + do_nmi(m_scan, m_cb2); +} + +void eacc_state::scan_w(int state) +{ + m_scan = state ? 1 : 0; + do_nmi(m_scan, m_cb2); +} + +uint8_t eacc_state::keyboard_r() +{ + uint8_t data = m_digit; + + for (uint8_t i = 3; i < 7; i++) + if (BIT(m_digit, i)) + data |= m_io_keyboard[i - 3]->read(); + + return data; +} + +void eacc_state::segment_w(uint8_t data) +{ + //d7 segment dot + //d6 segment c + //d5 segment d + //d4 segment e + //d3 segment a + //d2 segment b + //d1 segment f + //d0 segment g + + if (m_disp) + { + m_disp = false; + if (BIT(m_digit, 7)) + { + data ^= 0xff; + + for (uint8_t i = 0; i < 8; i++) + m_leds[i] = BIT(data, i); + } + else + { + for (uint8_t i = 3; i < 7; i++) + if (BIT(m_digit, i)) + m_digits[i] = bitswap<8>(data, 7, 0, 1, 4, 5, 6, 2, 3); + } + } +} + +void eacc_state::digit_w(uint8_t data) +{ + m_digit = data & 0xf8; + m_disp = true; +} + + +/****************************************************************************** + Machine Drivers +******************************************************************************/ + +void eacc_state::eacc(machine_config &config) +{ + /* basic machine hardware */ + M6802(config, m_maincpu, XTAL(3'579'545)); /* Divided by 4 inside the m6802*/ + m_maincpu->set_ram_enable(false); // FIXME: needs standby support + m_maincpu->set_addrmap(AS_PROGRAM, &eacc_state::mem_map); + + config.set_default_layout(layout_eacc); + + PIA6821(config, m_pia); + m_pia->readpb_handler().set(FUNC(eacc_state::keyboard_r)); + m_pia->writepa_handler().set(FUNC(eacc_state::segment_w)); + m_pia->writepb_handler().set(FUNC(eacc_state::digit_w)); + m_pia->cb2_handler().set(FUNC(eacc_state::cb2_w)); + m_pia->irqa_handler().set_inputline("maincpu", M6802_IRQ_LINE); + m_pia->irqb_handler().set_inputline("maincpu", M6802_IRQ_LINE); + + NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_0); + + TTL7474(config, m_7474, 0); + m_7474->output_cb().set(m_pia, FUNC(pia6821_device::cb1_w)); + + clock_device &eacc_scan(CLOCK(config, "eacc_scan", 600)); // 74C14 with 100k & 10nF = 1200Hz, but article says 600. + eacc_scan.signal_handler().set(FUNC(eacc_state::scan_w)); + + clock_device &eacc_cb1(CLOCK(config, "eacc_cb1", 15)); // cpu E -> MM5369 -> 15Hz + eacc_cb1.signal_handler().set(m_7474, FUNC(ttl7474_device::d_w)); + + clock_device &eacc_rnd(CLOCK(config, "eacc_rnd", 30)); // random pulse for distance and fuel + eacc_rnd.signal_handler().set(FUNC(eacc_state::inputs_w)); +} + + + +/****************************************************************************** + ROM Definitions +******************************************************************************/ + +ROM_START(eacc) + ROM_REGION(0x0800, "maincpu", 0) + ROM_LOAD("eacc.bin", 0x0000, 0x0800, CRC(287a63c0) SHA1(f61b397d33ea40e5742e34d5f5468572125e8b39) ) +ROM_END + +} // anonymous namespace + + +/****************************************************************************** + Drivers +******************************************************************************/ + +// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS +COMP( 1982, eacc, 0, 0, eacc, eacc, eacc_state, empty_init, "Electronics Australia", "EA Car Computer", MACHINE_NO_SOUND_HW | MACHINE_SUPPORTS_SAVE ) |