Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 56 additions & 0 deletions src/mame/layout/vw.lay
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<?xml version="1.0"?>
<!--
license:CC0-1.0

debugging display for Digijet ECU
-->

<mamelayout version="2">

<element name="led" defstate="0">
<disk state="0"> <color red="0.1" green="0.1" blue="0.1" /> </disk>
<disk state="1"> <color red="1.0" green="1.0" blue="0.1" /> </disk>
</element>

<element name="background">
<rect>
<bounds left="0" top="0" right="10" bottom="10" />
<color red="0.2" green="0.2" blue="0.2" />
</rect>
</element>

<element name="label_fuel">
<text string="Fuel pump">
<bounds left="0" top="0" right="1" bottom="0.4" />
<color red="1.0" green="1.0" blue="1.0" />
</text>
</element>
<element name="label_inject">
<text string="Injectors">
<bounds left="0" top="0" right="1" bottom="0.4" />
<color red="1.0" green="1.0" blue="1.0" />
</text>
</element>
<element name="label_check">
<text string="CHECK">
<bounds left="0" top="0" right="1" bottom="0.4" />
<color red="1.0" green="1.0" blue="1.0" />
</text>
<text string="ENGINE">
<bounds left="0" top="0.5" right="1" bottom="1" />
<color red="1.0" green="1.0" blue="1.0" />
</text>
</element>

<view name="Main">
<element ref="background"> <bounds left="0" right="7" top="0" bottom="5" /> </element>

<element ref="led" name="led_fuel"> <bounds left="1" right="2" top="1" bottom="2" /> </element>
<element ref="label_fuel"> <bounds left="1" right="2" top="2.2" bottom="2.6" /> </element>
<element ref="led" name="led_inject"> <bounds left="3" right="4" top="1" bottom="2" /> </element>
<element ref="label_inject"> <bounds left="3" right="4" top="2.2" bottom="2.6" /> </element>
<element ref="led" name="led_check"> <bounds left="5" right="6" top="1" bottom="2" /> </element>
<element ref="label_check"> <bounds left="5" right="6" top="2.2" bottom="2.6" /> </element>
</view>

</mamelayout>
1 change: 1 addition & 0 deletions src/mame/mame.lst
Original file line number Diff line number Diff line change
Expand Up @@ -43708,6 +43708,7 @@ digiblst

@source:skeleton/digijet.cpp
digijet
digijet90

@source:skeleton/digilog320.cpp
digilog320
Expand Down
206 changes: 192 additions & 14 deletions src/mame/skeleton/digijet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,71 +2,249 @@
// copyright-holders:Ryan Holtz
/*************************************************************************
drivers/digijet.cpp
skeleton/digijet.cpp
Skeleton driver for the Volkswagen Digijet series of automotive ECUs
The Digijet Engine Control Unit (ECU) was used in Volkswagen vehicles
from the early 1980s.
Currently, the only dump is from a 1985 Volkswagen Vanagon (USA CA).
from the 1980s.
CPU: MAF 80A39HL
ROM: ST M2764AF6
ADC0809CCN
LM2901
SN74LS373N
SN74LS00N
XTAL 7.372 MHz
_________________________
| 7 A 0 |
| 4 D 8 |
C 3 C 0 7 |
O 7 9 4 |
N L2 3 0 |
N M0 M2764AF6 X 0 |
| 91 80A39HL |
|________________________|
Connector
1 Engine RPM
2 Coolant temperture (ADC IN2)
3 GND
4 Throttle switch (T0)
5 Lambda sensor
6 GND Air sensor
7 GND
8 Check engine (not populated) (P1.3)
9 GND
10 GND
11 Injector (P1.5)
12 Injector (P1.5)
13 Ignition (ADC IN1)
14 Air in temperature (ADC IN3)
15 Air amount (ADC IN0)
16 GND
17 GND
18 GND
19 Air sensor power
20 Fuel pump (P1.4)
21 Fuel pump (P1.4)
22 GND
23 Injector (P1.5)
24 Injector (P1.5)
25 GND
**************************************************************************/

/*
TODO:
- Everything
- Figure out how the ADC is accessed
*/

#include "emu.h"
#include "cpu/mcs48/mcs48.h"
#include "machine/timer.h"
#include "machine/watchdog.h"

#include "vw.lh"

namespace {

#define I8049_TAG "i8049"

class digijet_state : public driver_device
{
public:
digijet_state(const machine_config &mconfig, device_type type, const char *tag)
: driver_device(mconfig, type, tag)
, m_maincpu(*this, I8049_TAG)
, m_maincpu(*this, "maincpu")
, m_watchdog(*this, "watchdog")
, m_rpm_timer(*this, "rpm")
, m_io_adc(*this, "ADC%u", 0U)
{
}

void digijet(machine_config &config);
void digijet90(machine_config &config);

private:
required_device<cpu_device> m_maincpu;
required_device<mcs48_cpu_device> m_maincpu;
required_device<watchdog_timer_device> m_watchdog;
required_device<timer_device> m_rpm_timer;
required_ioport_array<4> m_io_adc;

virtual void machine_start() override { }
virtual void machine_start() override ATTR_COLD;
virtual void machine_reset() override { }
void io_map(address_map &map) ATTR_COLD;
void prg_map(address_map &map) ATTR_COLD;

void p1_w(uint8_t data);

TIMER_DEVICE_CALLBACK_MEMBER( rpm_int );
uint8_t read_adc(offs_t offset);
void start_adc(uint8_t data);

bool m_rpm = false;
bool m_interrupt_enable = true;
};

void digijet_state::machine_start()
{
save_item(NAME(m_rpm));
save_item(NAME(m_interrupt_enable));
};

void digijet_state::io_map(address_map &map)
{
map(0x30, 0x3f).r(FUNC(digijet_state::read_adc));
map(0x30, 0x3f).w(FUNC(digijet_state::start_adc));
};

void digijet_state::prg_map(address_map &map)
{
map(0x000, 0x7ff).rom().region("maincpu", 0);
};

uint8_t digijet_state::read_adc(offs_t offset)
{
return m_io_adc[offset & 0x03]->read(); //FIXME this is a hack
// The address lines connected to the ADC are A8-A11 but those can't be accessed externally by this CPU
Copy link
Contributor

@ajrhacker ajrhacker Dec 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P20-P23 outputs are time-multiplexed with A8-A11 on MCS-48 parts executing from external memory.

I thought that the ADC hookup might use the PROG expander protocol, but from other comments that doesn't sound like the case here.

};

void digijet_state::start_adc(uint8_t data)
{
;// Connected to the START pin is the CPUs WR and the CPUs RD to the ADC OE and ALE
};

void digijet_state::p1_w(uint8_t data)
{
bool blockint = BIT(data, 0);
bool check = BIT(data,3);
bool fuel = BIT(data,4);
bool inject = BIT(data,5);
bool watchdog = BIT(data,6);

m_interrupt_enable = blockint;

machine().output().set_value("led_fuel", !fuel);
machine().output().set_value("led_inject", !inject);
machine().output().set_value("led_check", !check);

if (watchdog)
{
m_watchdog->watchdog_reset();
}
};

TIMER_DEVICE_CALLBACK_MEMBER(digijet_state::rpm_int)
{
if (m_interrupt_enable) {
m_maincpu->set_input_line(MCS48_INPUT_IRQ, m_rpm ? CLEAR_LINE : ASSERT_LINE);
m_rpm = !m_rpm;
} else {
m_maincpu->set_input_line(MCS48_INPUT_IRQ, CLEAR_LINE);
m_rpm = false;
}

}

static INPUT_PORTS_START( digijet )
PORT_START("ADC0")
PORT_BIT( 0xff, 0x80, IPT_PADDLE ) PORT_MINMAX(0x00, 0xff) PORT_SENSITIVITY(100) PORT_KEYDELTA(25) PORT_NAME("Air amount")

PORT_START("ADC1")
PORT_BIT( 0xff, 0x80, IPT_PEDAL ) PORT_MINMAX(0x00, 0xff) PORT_SENSITIVITY(35) PORT_KEYDELTA(10) PORT_NAME("Ignition")

PORT_START("ADC2")
PORT_BIT( 0xff, 0x80, IPT_PEDAL2 ) PORT_MINMAX(0x00, 0xff) PORT_SENSITIVITY(100) PORT_KEYDELTA(25) PORT_NAME("Coolant temperature")

PORT_START("ADC3")
PORT_BIT( 0xff, 0x80, IPT_PADDLE_V ) PORT_MINMAX(0x00, 0xff) PORT_SENSITIVITY(35) PORT_KEYDELTA(10) PORT_NAME("Air temperature")

PORT_START("LAMBDA")
PORT_BIT( 0x1f, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON1 )
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON2 )
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED )


PORT_START("THROTTLE")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON3 )

PORT_START("RPM")
PORT_BIT( 0xff, 0x80, IPT_PEDAL3 ) PORT_MINMAX(0x00, 0xff) PORT_SENSITIVITY(100) PORT_KEYDELTA(25) PORT_NAME("Engine RPM")
INPUT_PORTS_END

void digijet_state::digijet(machine_config &config)
{
/* basic machine hardware */
I8049(config, m_maincpu, XTAL(11'000'000));
I8039(config, m_maincpu, XTAL(11'000'000));

m_maincpu->set_addrmap(AS_PROGRAM, &digijet_state::prg_map);
m_maincpu->set_addrmap(AS_IO, &digijet_state::io_map);

m_maincpu->p1_out_cb().set(FUNC(digijet_state::p1_w));
m_maincpu->p2_in_cb().set_ioport("LAMBDA");
m_maincpu->t0_in_cb().set_ioport("THROTTLE");

WATCHDOG_TIMER(config, m_watchdog).set_time(attotime::from_msec(68)); // ???

TIMER(config, m_rpm_timer).configure_periodic(FUNC(digijet_state::rpm_int), attotime::from_hz(1000*2/60)); // 1000r/m * 2 (m_rpm toggle) / 60s

config.set_default_layout(layout_vw);
}

void digijet_state::digijet90(machine_config &config)
{
/* basic machine hardware */
I8039(config, m_maincpu, XTAL(7'372'800));

m_maincpu->set_addrmap(AS_PROGRAM, &digijet_state::prg_map);
m_maincpu->set_addrmap(AS_IO, &digijet_state::io_map);

m_maincpu->p1_out_cb().set(FUNC(digijet_state::p1_w));
m_maincpu->p2_in_cb().set_ioport("LAMBDA");
m_maincpu->t0_in_cb().set_ioport("THROTTLE");

WATCHDOG_TIMER(config, m_watchdog).set_time(attotime::from_msec(68)); // 0.68uF * 10kOhm

TIMER(config, m_rpm_timer).configure_periodic(FUNC(digijet_state::rpm_int), attotime::from_hz(1000*2/60)); // 1000r/m * 2 (m_rpm toggle) / 60s

config.set_default_layout(layout_vw);
}

ROM_START( digijet )
ROM_REGION( 0x800, I8049_TAG, 0 )
ROM_REGION( 0x800, "maincpu", 0 )
ROM_LOAD( "vanagon_85_usa_ca.bin", 0x000, 0x800, CRC(2ed7c4c5) SHA1(ae48d8892b44fe76b48bcefd293c15cd47af3fba) ) // Volkswagen Vanagon, 1985, USA, California
ROM_END

ROM_START( digijet90 )
ROM_REGION( 0x2000, "maincpu", 0 ) // repeats itself 4 times
ROM_LOAD( "fabb05_03_03.bin", 0x0000, 0x2000, CRC(8c96bcdf) SHA1(73b26914cd15ca3a5e0d7427de9ce4b4e311fb00) ) // Volkswagen 1990, Germany
ROM_END

} // anonymous namespace


// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS
CONS( 1985, digijet, 0, 0, digijet, digijet, digijet_state, empty_init, "Volkswagen", "Digijet", MACHINE_NOT_WORKING | MACHINE_NO_SOUND_HW )
// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS
CONS( 1985, digijet, digijet90, 0, digijet, digijet, digijet_state, empty_init, "Volkswagen", "Digijet", MACHINE_NOT_WORKING | MACHINE_NO_SOUND_HW )
CONS( 1990, digijet90, 0, 0, digijet90, digijet, digijet_state, empty_init, "Volkswagen", "Digijet (1990)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND_HW )
Loading