|
| 1 | +// license:BSD-3-Clause |
| 2 | +// copyright-holders:Nigel Barnes |
| 3 | +/****************************************************************************** |
| 4 | +
|
| 5 | + Thaler CT-65 / MPS-65 |
| 6 | +
|
| 7 | + TODO: |
| 8 | + - CT-65 cassette interface (add-on board for MPS-65) |
| 9 | +
|
| 10 | +******************************************************************************/ |
| 11 | + |
| 12 | +#include "emu.h" |
| 13 | +#include "cpu/m6502/m6502.h" |
| 14 | +#include "machine/6522via.h" |
| 15 | + |
| 16 | +#include "mps65.lh" |
| 17 | + |
| 18 | + |
| 19 | +namespace { |
| 20 | + |
| 21 | +class mps65_state : public driver_device |
| 22 | +{ |
| 23 | +public: |
| 24 | + mps65_state(const machine_config &mconfig, device_type type, const char *tag) |
| 25 | + : driver_device(mconfig, type, tag) |
| 26 | + , m_maincpu(*this, "maincpu") |
| 27 | + , m_keypad(*this, "COL%u", 1U) |
| 28 | + , m_digit(*this, "digit%u", 1U) |
| 29 | + , m_keycol(0) |
| 30 | + { } |
| 31 | + |
| 32 | + void mps65(machine_config &config); |
| 33 | + |
| 34 | + DECLARE_INPUT_CHANGED_MEMBER(reset_changed); |
| 35 | + |
| 36 | +protected: |
| 37 | + virtual void machine_start() override; |
| 38 | + |
| 39 | +private: |
| 40 | + required_device<cpu_device> m_maincpu; |
| 41 | + required_ioport_array<6> m_keypad; |
| 42 | + output_finder<6> m_digit; |
| 43 | + |
| 44 | + void mps65_map(address_map &map); |
| 45 | + |
| 46 | + uint8_t pa_r(); |
| 47 | + void pa_w(uint8_t data); |
| 48 | + void pb_w(uint8_t data); |
| 49 | + |
| 50 | + uint8_t m_keycol; |
| 51 | +}; |
| 52 | + |
| 53 | + |
| 54 | +void mps65_state::machine_start() |
| 55 | +{ |
| 56 | + m_digit.resolve(); |
| 57 | + |
| 58 | + save_item(NAME(m_keycol)); |
| 59 | +} |
| 60 | + |
| 61 | + |
| 62 | +uint8_t mps65_state::pa_r() |
| 63 | +{ |
| 64 | + uint8_t data = 0xff; |
| 65 | + |
| 66 | + if (m_keycol > 0 && m_keycol < 7) |
| 67 | + data = m_keypad[m_keycol - 1]->read() & 0x0f; |
| 68 | + |
| 69 | + return data; |
| 70 | +} |
| 71 | + |
| 72 | +void mps65_state::pa_w(uint8_t data) |
| 73 | +{ |
| 74 | + m_keycol = (data >> 4) & 7; |
| 75 | +} |
| 76 | + |
| 77 | +void mps65_state::pb_w(uint8_t data) |
| 78 | +{ |
| 79 | + if (m_keycol > 0 && m_keycol < 7) |
| 80 | + { |
| 81 | + m_digit[m_keycol - 1] = bitswap<8>(data, 7, 3, 5, 0, 1, 2, 4, 6) & 0x7f; |
| 82 | + } |
| 83 | +} |
| 84 | + |
| 85 | + |
| 86 | +void mps65_state::mps65_map(address_map &map) |
| 87 | +{ |
| 88 | + map(0x0000, 0x07ff).ram(); |
| 89 | + map(0xa000, 0xa00f).mirror(0xf0).m("via", FUNC(via6522_device::map)); |
| 90 | + map(0xf000, 0xffff).rom().region("rom", 0); |
| 91 | +} |
| 92 | + |
| 93 | + |
| 94 | +static INPUT_PORTS_START( mps65 ) |
| 95 | + PORT_START("COL1") |
| 96 | + PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_C) PORT_CHAR('C') |
| 97 | + PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_8) PORT_CHAR('8') |
| 98 | + PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_4) PORT_CHAR('4') |
| 99 | + PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_0) PORT_CHAR('0') |
| 100 | + |
| 101 | + PORT_START("COL2") |
| 102 | + PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_D) PORT_CHAR('D') |
| 103 | + PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_9) PORT_CHAR('9') |
| 104 | + PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_5) PORT_CHAR('5') |
| 105 | + PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_1) PORT_CHAR('1') |
| 106 | + |
| 107 | + PORT_START("COL3") |
| 108 | + PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_E) PORT_CHAR('E') |
| 109 | + PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_A) PORT_CHAR('A') |
| 110 | + PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_6) PORT_CHAR('6') |
| 111 | + PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_2) PORT_CHAR('2') |
| 112 | + |
| 113 | + PORT_START("COL4") |
| 114 | + PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F) PORT_CHAR('F') |
| 115 | + PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_B) PORT_CHAR('B') |
| 116 | + PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_7) PORT_CHAR('7') |
| 117 | + PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_3) PORT_CHAR('3') |
| 118 | + |
| 119 | + PORT_START("COL5") |
| 120 | + PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_G) PORT_CHAR('G') PORT_NAME("Go") |
| 121 | + PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_S) PORT_CHAR('S') PORT_NAME("Save") |
| 122 | + PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_L) PORT_CHAR('L') PORT_NAME("Load") |
| 123 | + PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_M) PORT_CHAR('M') PORT_NAME("Address") |
| 124 | + |
| 125 | + PORT_START("COL6") |
| 126 | + PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED) |
| 127 | + PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_I) PORT_CHAR('I') PORT_NAME("Index") |
| 128 | + PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_S) PORT_CHAR('S') PORT_NAME("Backstep") |
| 129 | + PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_ENTER) PORT_CHAR(13) PORT_NAME("Enter") |
| 130 | + |
| 131 | + PORT_START("RESET") |
| 132 | + PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_R) PORT_NAME("Reset") PORT_CHANGED_MEMBER(DEVICE_SELF, mps65_state, reset_changed, 0) |
| 133 | +INPUT_PORTS_END |
| 134 | + |
| 135 | + |
| 136 | +INPUT_CHANGED_MEMBER(mps65_state::reset_changed) |
| 137 | +{ |
| 138 | + m_maincpu->set_input_line(INPUT_LINE_RESET, newval ? CLEAR_LINE : ASSERT_LINE); |
| 139 | + |
| 140 | + if (newval) |
| 141 | + { |
| 142 | + machine().schedule_soft_reset(); |
| 143 | + } |
| 144 | +} |
| 145 | + |
| 146 | + |
| 147 | +void mps65_state::mps65(machine_config &config) |
| 148 | +{ |
| 149 | + M6502(config, m_maincpu, 1_MHz_XTAL); |
| 150 | + m_maincpu->set_addrmap(AS_PROGRAM, &mps65_state::mps65_map); |
| 151 | + |
| 152 | + config.set_default_layout(layout_mps65); |
| 153 | + |
| 154 | + via6522_device &via(MOS6522(config, "via", 1_MHz_XTAL)); |
| 155 | + via.readpa_handler().set(FUNC(mps65_state::pa_r)); |
| 156 | + via.writepa_handler().set(FUNC(mps65_state::pa_w)); |
| 157 | + via.writepb_handler().set(FUNC(mps65_state::pb_w)); |
| 158 | + via.irq_handler().set_inputline(m_maincpu, M6502_IRQ_LINE); |
| 159 | +} |
| 160 | + |
| 161 | + |
| 162 | +ROM_START( ct65 ) |
| 163 | + ROM_REGION(0x1000, "rom", 0) |
| 164 | + ROM_LOAD("ct6502.bin", 0x0000, 0x1000, CRC(832e0d2a) SHA1(f5f7d00360747a194fca01fb95f31c092505b523)) |
| 165 | +ROM_END |
| 166 | + |
| 167 | +ROM_START( mps65 ) |
| 168 | + ROM_REGION(0x1000, "rom", 0) |
| 169 | + ROM_LOAD("mps65.bin", 0x0800, 0x0800, CRC(512c8cde) SHA1(b6a43ad26d30bcf088b72f3c29e9bcbbf371f4cf)) |
| 170 | +ROM_END |
| 171 | + |
| 172 | +} // anonymous namespace |
| 173 | + |
| 174 | + |
| 175 | +// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS |
| 176 | +COMP( 1982, ct65, mps65, 0, mps65, mps65, mps65_state, empty_init, "Thaler", "CT-65", MACHINE_NO_SOUND_HW ) |
| 177 | +COMP( 1984, mps65, 0, 0, mps65, mps65, mps65_state, empty_init, "Thaler", "MPS-65", MACHINE_NO_SOUND_HW ) |
0 commit comments