New working systems

-------------------
Addometer Calculator [hap, Sean Riddle]
This commit is contained in:
hap 2023-06-04 15:01:26 +02:00
parent e711951979
commit 44feade33f
10 changed files with 265 additions and 23 deletions

View file

@ -143,7 +143,8 @@ INPUT_CHANGED_MEMBER(hh_cop400_state::reset_button)
INPUT_CHANGED_MEMBER(hh_cop400_state::power_button)
{
set_power((bool)param);
if (newval != field.defvalue())
set_power((bool)param);
}
void hh_cop400_state::set_power(bool state)

View file

@ -190,7 +190,8 @@ INPUT_CHANGED_MEMBER(hh_pic16_state::reset_button)
INPUT_CHANGED_MEMBER(hh_pic16_state::power_button)
{
set_power((bool)param);
if (newval != field.defvalue())
set_power((bool)param);
}
void hh_pic16_state::set_power(bool state)

View file

@ -16,6 +16,7 @@ ROM source notes when dumped from another title, but confident it's the same:
#include "cpu/pps41/mm76.h"
#include "cpu/pps41/mm78.h"
#include "cpu/pps41/mm78la.h"
#include "machine/timer.h"
#include "sound/beep.h"
#include "sound/spkrdev.h"
#include "video/pwm.h"
@ -24,6 +25,7 @@ ROM source notes when dumped from another title, but confident it's the same:
#include "speaker.h"
// internal artwork
#include "addocalc.lh"
#include "brainbaf.lh"
#include "dunksunk.lh"
#include "ftri1.lh"
@ -53,6 +55,7 @@ public:
{ }
virtual DECLARE_INPUT_CHANGED_MEMBER(reset_button);
virtual DECLARE_INPUT_CHANGED_MEMBER(power_button);
protected:
virtual void machine_start() override;
@ -72,8 +75,11 @@ protected:
// MCU output pin state
u16 m_d = 0;
u16 m_r = 0;
u8 m_ssc = 0;
u8 m_sdo = 0;
u8 read_inputs(int columns);
void set_power(bool state);
virtual void update_int() { ; }
};
@ -88,6 +94,8 @@ void hh_pps41_state::machine_start()
save_item(NAME(m_plate));
save_item(NAME(m_d));
save_item(NAME(m_r));
save_item(NAME(m_ssc));
save_item(NAME(m_sdo));
}
@ -118,6 +126,20 @@ INPUT_CHANGED_MEMBER(hh_pps41_state::reset_button)
m_maincpu->set_input_line(INPUT_LINE_RESET, newval ? ASSERT_LINE : CLEAR_LINE);
}
INPUT_CHANGED_MEMBER(hh_pps41_state::power_button)
{
if (newval != field.defvalue())
set_power((bool)param);
}
void hh_pps41_state::set_power(bool state)
{
m_maincpu->set_input_line(INPUT_LINE_RESET, state ? CLEAR_LINE : ASSERT_LINE);
if (m_display && !state)
m_display->clear();
}
/*******************************************************************************
@ -126,6 +148,176 @@ INPUT_CHANGED_MEMBER(hh_pps41_state::reset_button)
*******************************************************************************/
/*******************************************************************************
Addometer Company Addometer Calculator
* MM78 MCU (label MM78 A7872-11, die label A7872)
* 12-digit 7seg VFD, 1 digit unused (NEC LD8197A/FIP12A4A 0B)
This is presumably the only pocket calculator by Addometer Company (previously
known as Reliable Typewriter and Adding Machine Corporation). It's a feet
and inches/metric calculator.
*******************************************************************************/
class addocalc_state : public hh_pps41_state
{
public:
addocalc_state(const machine_config &mconfig, device_type type, const char *tag) :
hh_pps41_state(mconfig, type, tag),
m_power_timer(*this, "power")
{ }
void addocalc(machine_config &config);
virtual DECLARE_INPUT_CHANGED_MEMBER(power_button) override { hh_pps41_state::power_button(field, param, oldval, newval); update_int(); }
private:
required_device<timer_device> m_power_timer;
virtual void update_int() override;
void update_display();
void write_d(u16 data);
void write_r(u16 data);
u8 read_p();
void write_ssc(int state);
void write_sdo(int state);
TIMER_DEVICE_CALLBACK_MEMBER(power_off) { set_power(false); }
};
// handlers
void addocalc_state::update_int()
{
// ON/OFF button is tied to INT1
m_maincpu->set_input_line(1, (m_inputs[7]->read() & 1) ? ASSERT_LINE : CLEAR_LINE);
}
void addocalc_state::update_display()
{
m_display->matrix(m_d | m_ssc << 10, bitswap<8>(~m_r, 0,1,2,3,4,5,6,7));
}
void addocalc_state::write_d(u16 data)
{
// DIO0-DIO9: digit select
// DIO0-DIO6: input mux
m_d = m_inp_mux = data;
update_display();
}
void addocalc_state::write_r(u16 data)
{
// RIO1-RIO8: digit segment data
m_r = data;
update_display();
}
u8 addocalc_state::read_p()
{
// PI1-PI4: multiplexed inputs
return ~read_inputs(7);
}
void addocalc_state::write_ssc(int state)
{
// CLOCK: one more digit
m_ssc = state;
update_display();
}
void addocalc_state::write_sdo(int state)
{
// DATAO: trigger power off after a short delay
if (state != m_sdo)
m_power_timer->adjust(state ? attotime::from_msec(50) : attotime::never);
m_sdo = state;
}
// inputs
static INPUT_PORTS_START( addocalc )
PORT_START("IN.0") // DIO0
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_UNUSED )
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_DEL) PORT_CODE(KEYCODE_BACKSPACE) PORT_NAME("CL")
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_ENTER) PORT_CODE(KEYCODE_ENTER_PAD) PORT_NAME("=")
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_UNUSED )
PORT_START("IN.1") // DIO1
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_PLUS_PAD) PORT_NAME("+")
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_MINUS_PAD) PORT_NAME("-")
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_ASTERISK) PORT_NAME(u8"×")
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_SLASH_PAD) PORT_NAME(u8"÷")
PORT_START("IN.2") // DIO2
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_S) PORT_NAME("STO")
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_R) PORT_NAME("REC")
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_E) PORT_NAME("EX")
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_STOP) PORT_CODE(KEYCODE_DEL_PAD) PORT_NAME(".")
PORT_START("IN.3") // DIO3
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_F) PORT_NAME("FT")
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_I) PORT_NAME("IN")
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_A) PORT_NAME("FRA")
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_M) PORT_NAME("MET")
PORT_START("IN.4") // DIO4
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_0) PORT_CODE(KEYCODE_0_PAD) PORT_NAME("0")
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_1) PORT_CODE(KEYCODE_1_PAD) PORT_NAME("1")
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_2) PORT_CODE(KEYCODE_2_PAD) PORT_NAME("2")
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_3) PORT_CODE(KEYCODE_3_PAD) PORT_NAME("3")
PORT_START("IN.5") // DIO5
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_4) PORT_CODE(KEYCODE_4_PAD) PORT_NAME("4")
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_5) PORT_CODE(KEYCODE_5_PAD) PORT_NAME("5")
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_6) PORT_CODE(KEYCODE_6_PAD) PORT_NAME("6")
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_7) PORT_CODE(KEYCODE_7_PAD) PORT_NAME("7")
PORT_START("IN.6") // DIO6
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_8) PORT_CODE(KEYCODE_8_PAD) PORT_NAME("8")
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_9) PORT_CODE(KEYCODE_9_PAD) PORT_NAME("9")
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_UNUSED )
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_UNUSED )
PORT_START("IN.7") // INT1
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_POWER_ON ) PORT_CHANGED_MEMBER(DEVICE_SELF, addocalc_state, power_button, true) PORT_NAME("ON/OFF")
INPUT_PORTS_END
// config
void addocalc_state::addocalc(machine_config &config)
{
// basic machine hardware
MM78(config, m_maincpu, 430000); // approximation - VC osc. R=47K
m_maincpu->write_d().set(FUNC(addocalc_state::write_d));
m_maincpu->write_r().set(FUNC(addocalc_state::write_r));
m_maincpu->read_p().set(FUNC(addocalc_state::read_p));
m_maincpu->write_ssc().set(FUNC(addocalc_state::write_ssc));
m_maincpu->write_sdo().set(FUNC(addocalc_state::write_sdo));
TIMER(config, "power").configure_generic(FUNC(addocalc_state::power_off));
// video hardware
PWM_DISPLAY(config, m_display).set_size(11, 8);
m_display->set_segmask(0x7ff, 0xff);
config.set_default_layout(layout_addocalc);
// no sound!
}
// roms
ROM_START( addocalc )
ROM_REGION( 0x0800, "maincpu", 0 )
ROM_LOAD( "mm78_a7872-11", 0x0000, 0x0800, CRC(1ff26da7) SHA1(b4b9b5886d60dcd634661604f9ef5346a6c8bd1b) )
ROM_END
/*******************************************************************************
Fonas Tri-1
@ -197,7 +389,7 @@ static INPUT_PORTS_START( ftri1 )
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("Swing / S2 V")
PORT_START("RESET")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CHANGED_MEMBER(DEVICE_SELF, hh_pps41_state, reset_button, 0) PORT_CODE(KEYCODE_F1) PORT_NAME("Game Reset")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CHANGED_MEMBER(DEVICE_SELF, ftri1_state, reset_button, 0) PORT_CODE(KEYCODE_F1) PORT_NAME("Game Reset")
INPUT_PORTS_END
// config
@ -1616,6 +1808,8 @@ ROM_END
*******************************************************************************/
// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY, FULLNAME, FLAGS
SYST( 1980, addocalc, 0, 0, addocalc, addocalc, addocalc_state, empty_init, "Addometer Company", "Addometer Calculator", MACHINE_SUPPORTS_SAVE | MACHINE_NO_SOUND_HW )
SYST( 1979, ftri1, 0, 0, ftri1, ftri1, ftri1_state, empty_init, "Fonas", "Tri-1 (Fonas)", MACHINE_SUPPORTS_SAVE )
SYST( 1979, mastmind, 0, 0, mastmind, mastmind, mastmind_state, empty_init, "Invicta", "Electronic Master Mind (Invicta)", MACHINE_SUPPORTS_SAVE | MACHINE_NO_SOUND_HW )

View file

@ -480,7 +480,8 @@ INPUT_CHANGED_MEMBER(hh_tms1k_state::reset_button)
INPUT_CHANGED_MEMBER(hh_tms1k_state::power_button)
{
set_power((bool)param);
if (newval != field.defvalue())
set_power((bool)param);
}
void hh_tms1k_state::auto_power_off(int state)

View file

@ -415,8 +415,7 @@ void iteagle_fpga_device::fpga_w(offs_t offset, uint32_t data, uint32_t mem_mask
if (VERBOSE & LOG_SERIAL) {
m_serial0_1.write_data((data >> 16) & 0xff, 1);
if (m_serial0_1.get_tx_str(1).back() == 0xd) {
logerror("com0: %s", m_serial0_1.get_tx_str(1).c_str());
osd_printf_info("com0: %s\n", m_serial0_1.get_tx_str(1));
LOGMASKED(LOG_SERIAL, "com0: %s\n", m_serial0_1.get_tx_str(1));
m_serial0_1.clear_tx_str(1);
}
}
@ -465,7 +464,7 @@ void iteagle_fpga_device::fpga_w(offs_t offset, uint32_t data, uint32_t mem_mask
int chan = 0;
m_serial2_3.write_data((data >> 24) & 0xff, chan);
if (m_serial2_3.get_tx_str(chan).back() == 0xd) {
LOGMASKED(LOG_SERIAL, "com3: %s\n", m_serial2_3.get_tx_str(chan).c_str());
LOGMASKED(LOG_SERIAL, "com3: %s\n", m_serial2_3.get_tx_str(chan));
osd_printf_debug("com3: %s\n", m_serial2_3.get_tx_str(chan));
if (m_serial2_3.get_tx_str(chan).find("ATI5") != -1)
m_serial2_3.write_rx_str(chan, "OK\r181\r");
@ -530,7 +529,7 @@ uint8_t iteagle_am85c30::read_control(int channel)
void iteagle_am85c30::write_data(uint8_t data, int channel)
{
if (VERBOSE & LOG_SERIAL_VERBOSE) printf("chan %i: TX 0x%2X\n", channel, data);
//osd_printf_debug("chan %i: TX 0x%2X\n", channel, data);
m_serial_tx[channel] += data;
m_rr_regs[channel][0] |= 0x4; // Tx Buffer Empty
// Tx Interrupt
@ -541,7 +540,6 @@ void iteagle_am85c30::write_data(uint8_t data, int channel)
}
// Limit length
if (m_serial_tx[channel].size() >= 4000) {
if (VERBOSE & LOG_SERIAL) printf("%s\n", m_serial_tx[channel].c_str());
osd_printf_debug("%s\n", m_serial_tx[channel]);
m_serial_tx[channel].clear();
}
@ -551,7 +549,7 @@ uint8_t iteagle_am85c30::read_data(int channel)
{
uint8_t retVal = 0;
if (!m_serial_rx[channel].empty()) {
//logerror("fpga_r: read byte: %c\n", m_serial_rx[channel].at(0));
//printf("fpga_r: read byte: %c\n", m_serial_rx[channel].at(0));
retVal = m_serial_rx[channel].at(0);
m_serial_rx[channel].erase(m_serial_rx[channel].begin());
}
@ -709,7 +707,7 @@ void iteagle_eeprom_device::device_start()
uint16_t checkSum = 0;
for (int i=0; i<0x3f; i++) {
checkSum += m_iteagle_default_eeprom[i];
//logerror("eeprom init i: %x data: %04x\n", i, iteagle_default_eeprom[i]);
//logerror("eeprom init i: %x data: %04x\n", i, iteagle_default_eeprom[i]);
}
m_iteagle_default_eeprom[0x3f] = checkSum;

View file

@ -27,6 +27,7 @@ public:
std::string get_tx_str(int channel) { return m_serial_tx[channel]; }
void clear_tx_str(int channel) { m_serial_tx[channel].clear(); }
bool check_interrupt() { return (m_rr_regs[0][3] != 0); }
private:
uint8_t m_rr_regs[2][16];
uint8_t m_wr_regs[2][16];
@ -80,7 +81,7 @@ private:
devcb_read16 m_gunx_cb;
devcb_read16 m_guny_cb;
emu_timer * m_timer;
emu_timer *m_timer;
int m_irq_num;
int m_serial_irq_num;
@ -169,7 +170,6 @@ private:
uint32_t ctrl_r(offs_t offset, uint32_t mem_mask = ~0);
void ctrl_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
};
DECLARE_DEVICE_TYPE(ITEAGLE_FPGA, iteagle_fpga_device)

View file

@ -0,0 +1,48 @@
<?xml version="1.0"?>
<!--
license:CC0-1.0
-->
<mamelayout version="2">
<!-- define elements -->
<element name="mul"><rect><color red="0.8" green="0.8" blue="0.8" /></rect></element>
<element name="text_l1"><text string="m" align="2"></text></element>
<element name="text_l2"><text string="cm" align="2"></text></element>
<element name="text_l3"><text string="stor" align="2"></text></element>
<element name="digit" defstate="0">
<led7seg><color red="0.2" green="1.0" blue="0.85" /></led7seg>
</element>
<!-- build screen -->
<view name="Internal Layout">
<!-- labels -->
<collection name="Labels">
<element ref="text_l1"><bounds x="28.5" y="17" width="10" height="5" /></element>
<element ref="text_l2"><bounds x="48.5" y="17" width="10" height="5" /></element>
<element ref="text_l3"><bounds x="114.5" y="17" width="10" height="5" /></element>
<element ref="mul" blend="multiply"><bounds x="-5" y="-3" width="130" height="27" /></element>
</collection>
<!-- display -->
<element name="digit0" ref="digit"><bounds x="0" y="0" width="10" height="15" /></element>
<element name="digit1" ref="digit"><bounds x="10" y="0" width="10" height="15" /></element>
<element name="digit2" ref="digit"><bounds x="20" y="0" width="10" height="15" /></element>
<element name="digit3" ref="digit"><bounds x="30" y="0" width="10" height="15" /></element>
<element name="digit4" ref="digit"><bounds x="40" y="0" width="10" height="15" /></element>
<element name="digit5" ref="digit"><bounds x="50" y="0" width="10" height="15" /></element>
<element ref="digit"><bounds x="60" y="0" width="10" height="15" /></element> <!-- N/C -->
<element name="digit6" ref="digit"><bounds x="70" y="0" width="10" height="15" /></element>
<element name="digit7" ref="digit"><bounds x="80" y="0" width="10" height="15" /></element>
<element name="digit10" ref="digit"><bounds x="90" y="0" width="10" height="15" /></element>
<element name="digit8" ref="digit"><bounds x="100" y="0" width="10" height="15" /></element>
<element name="digit9" ref="digit"><bounds x="110" y="0" width="10" height="15" /></element>
</view>
</mamelayout>

View file

@ -18740,6 +18740,7 @@ us2pfball // US Games
uspbball // US Games
@source:handheld/hh_pps41.cpp
addocalc // Addometer Company
brainbaf // Mattel
dunksunk // Kmart
ftri1 // Fonas

View file

@ -30,7 +30,6 @@ TODO:
#include "emu.h"
#include "cpu/mcs48/mcs48.h"
#include "machine/timer.h"
#include "machine/tms6100.h"
#include "video/mm5445.h"
#include "video/pwm.h"
@ -54,7 +53,6 @@ public:
m_display(*this, "display"),
m_tms6100(*this, "tms6100"),
m_speech(*this, "speech"),
m_onbutton_timer(*this, "on_button"),
m_inputs(*this, "IN.%u", 0)
{ }
@ -73,10 +71,10 @@ private:
required_device<pwm_display_device> m_display;
required_device<tms6100_device> m_tms6100;
required_device<votrax_sc01_device> m_speech;
required_device<timer_device> m_onbutton_timer;
required_ioport_array<7> m_inputs;
bool m_power_on = false;
attotime m_onbutton_time;
u8 m_inp_mux = 0;
u8 m_phoneme = 0x3f;
int m_speech_strobe = 0;
@ -95,6 +93,7 @@ void k28_state::machine_start()
{
// register for savestates
save_item(NAME(m_power_on));
save_item(NAME(m_onbutton_time));
save_item(NAME(m_inp_mux));
save_item(NAME(m_phoneme));
save_item(NAME(m_speech_strobe));
@ -112,8 +111,8 @@ void k28_state::machine_reset()
m_power_on = true;
m_maincpu->set_input_line(INPUT_LINE_RESET, CLEAR_LINE);
// the game relies on reading the on-button as pressed when it's turned on
m_onbutton_timer->adjust(attotime::from_msec(250));
// it relies on reading the on-button as pressed when it's turned on
m_onbutton_time = machine().time() + attotime::from_msec(250);
}
INPUT_CHANGED_MEMBER(k28_state::power_on)
@ -126,6 +125,7 @@ void k28_state::power_off()
{
m_power_on = false;
m_maincpu->set_input_line(INPUT_LINE_RESET, ASSERT_LINE);
m_display->clear();
}
@ -189,7 +189,7 @@ u8 k28_state::mcu_p1_r()
data |= m_inputs[i]->read();
// force press on-button at boot
if (i == 5 && m_onbutton_timer->enabled())
if (i == 5 && machine().time() < m_onbutton_time)
data |= 1;
}
@ -310,8 +310,6 @@ void k28_state::k28(machine_config &config)
TMS6100(config, m_tms6100, 3.579545_MHz_XTAL / 15); // CLK tied to 8021 ALE pin
TIMER(config, "on_button").configure_generic(nullptr);
// video hardware
MM5445(config, m_vfd).output_cb().set(FUNC(k28_state::vfd_output_w));
PWM_DISPLAY(config, m_display).set_size(9, 16);

View file

@ -7,8 +7,8 @@ Tiger Electronics K-2-8 (model 7-232) Sold in Hong Kong, distributed in US as:
- Coleco: Talking Teacher (model 8100)
- Sears: Talkatron: Learning Computer
1981 K-2-8 models 7-230 and 7-231 are on different hardware, showing a different
keyboard, VFD, and use the SC-01 speech chip. --> driver k28.cpp
1981 K-2-8 models 7-230 and 7-231 are on different hardware, having a different
keyboard, VFD, and the SC-01-A speech chip. --> driver k28.cpp
Hardware notes:
- PCB label: 201223A (main), REV0 ET828D (LCD)