Dual Table Code


The 'Dual Table' embedded code for MegaSquirt® EFI controllers provides some additional control options for advanced MegaSquirt® users. The Dual Table code for MegaSquirt® was written primarily by Eric Fahlgren, who also creates the MegaTune tuning software. When he initially developed the Dual Table code for the MegaSquirt® fuel injection controller, his motive was to run normal fuel injection on bank 1 and water injection for his turbocharged engine on bank 2. When Guy Hill took over the embedded code side for a while, he was planning on using bank 2 to control a proportional nitrous oxide injection system. Both Eric and Guy ensured that developments of the Dual Table code would support lots of other creative applications, like staged injection and so on.

Dual Table code should only be used to stage injectors when you have need for a huge dynamic range in fuel needs, for example, a 1.0 liter motor that puts out 500+ HP but must idle well. If you are running naturally aspirated, then staging is pretty much an exercise in unnecessary complexity.

Eric still refers to the Dual Table code as 'experimental', but there are enough MegaSquirts running the Dual Table code in the real world now that you can be fairly confident of its operation.

A couple guys are running it to stage injectors on rotary engines, a couple more are using it for water injection on bank two, more are running it for non-Dual Table usage features like rev-limit, idle control and some have even tried to make the boost controller work.

Dual Table Code Features

The latest version of the Dual Table code (1.02) has a number of features. In addition to the standard features of MegaSquirt® code version 2.986 (including PWM disable during cranking), these include:

These will be discussed in turn:

Independent Injector Bank Settings

Independent injection control for each injector bank which allows completely separate VE entries, kPa and RPM bins, control algorithms, and PWM values. The same enrichments are used for both banks, however you have the option of disabling enrichments for either bank. This means you have independent control of the two injector banks, almost as if you had two MegaSquirts operating them.


This allows you to implement a 'hard' fuel cut at a user-specified RPM. It is user settable (from 100 to 25,500 rpm) and can be disabled if desired (by entering a value of zero). Details on how to set the rev limiter are below.

PWM Idle speed control

The Dual Table has pulse width modulation (PWM) fast-idle control. The idle is active high at the microcontroller and active low at the interface connector with the standard transistor driver as supplied with Megasquirt. The coding was done by Brian Fielding. His algorithm was integrated into the dual table code. Eric had to move the variables around in memory, most notably the runtime value for idle DC, so his version of MegaTune won't work with this code, but other than that it should work the same.

The Dual Table code idle controller works with a spring loaded idle control valve. You will need a driver circuit to control the idle valve. The driver circuit can be just like the injector driver circuit on the MegaSquirt® board, which is what Eric has implemented on his daughter board, with FETs and full flyback control.

Note that the Dual Table fast idle control is for 'solenoid' type idle controllers - NOT for stepper type IAC motors.

N2O injection control

One of Guy Hill's original reasons for working on the Dual Table code was to be able to run mapped ("dry") nitrous oxide (N2O) control on one bank and fuel on the other. This can be accomplished with the current code using fuel on one injector bank and nitrous on the other injector bank. The only problem is that the controllable nitrous solenoids are expensive (about US$250 each).

The Dual Table code also has a much simpler alternative to Guy's mapped 'dry' nitrous oxide injection system, in the form of a single output to control a 'wet' nitrous oxide system. It turns on when 3-4 conditions dictate, for example RPM within a certain range, Coolant Temperature above lower limit, throttle is above some percentage, etc.

Making a wet system work is really quite simple. Make sure you jet it right and turn it on. One missing safety feature is a fuel pressure input (which would be nice for most hi-po motors anyhow), but that should be pretty easy to add if you are so inclined (use one of the two open ADC inputs) by using Eric's daughter board, and is left as an exercise for the user.

Boost Control

For controlling turbocharger wastegate control devices using a variable voltage signal using a PD (proportional differential) controller algorithm, running PTA2 (pin 35) at user-definable PWM rate. Note that Dual Table code Version 1.02 incorporates minor boost controller tweaks which are still highly experimental. The use of the gain variables was too touchy in previous versions, so Eric has made them less sensitive.

Eric might rework the boost control logic from the ground up, so don't be surprised if this feature changes in future versions. You will need Eric's daughter board (or something similar) to implemnent this (and some other) features of the Dual Table code.

Shift Light

The dual table code has a four-state shift light added. This is currently coded to drive the unused pins on port c, as follows:
PTC3pin 10Shift light LSB
PTC4pin 11Shift light MSB

The shift light has two RPM limits, below the lower limit the two pins present logic 00, when you hit the lower limit they go to 01, when the midpoint between the limits is reached, they change state to 10 and when the upper limit is reached they go to 11. If you put a 2->4 decoder on these two pins, you can have a progressive shift light like you see on LMP cars.

Launch Control

A new launch control feature (secondary rev limit) is enabled through PTA7. This is pin 40 of the 68HC908GP32 microprocessor in MegaSquirt. It is sent out to X0 on the V2.2 MegaSquirt® board and to H3:7 on Eric's daughter board, if you have one. Just ground the pin through a 1k resistor to turn on the feature.

The launch control hardware interferes with the B&G external flyback board, which uses pins 39 and 40 (X1 and X0, respectively) to control the flyback. Contact Eric Fahlgren if you need to have both.

Zero Pulse

Eric specifically coded into the dual table code that zero VE means exactly no injector pulse at all. So if the VE table returns a zero value, then all other calculations (enrichments, OC time and all that) are ignored, the PW is set to zero, and the injectors do not get a pulse. This feature is essential to prevent secondary injectors (and nitrous systems) from injecting before they are commanded. (Note that in standard MegaSquirt® embedded code, a zero VE still results in a pulsewidth that includes the injector opening time as well as some enrichments).

Crank Mode

In addition to disabling pulse width modulation (PWM) during cranking, the Dual Table code sets a clock on cranking mode; after 30 seconds of running you cannot go back into cranking without rebooting (i.e. turning the igntion off), even if RPM drops below 300. This prevents the cranking enrichment from being activated and flooding/stalling the engine in very low rpm situations, such as off-roading.

The dual table code has other features as well. Eric added an option to the dual table code that allows you to select between a fixed-time pump shot and an ignition-count pump shot. After some discussion on the list about basing after start enrichment (ASE) on time rather than ignition events, Eric got to thinking that the opposite might be reasonable for acceleration enrichments (AE). He has been using the AE 'count' mode for a while and it seems to work just as well at all revs, but uses far less fuel at high revs.

Eric has also added an option to allow EGO closed loop control to be time-based, too. The "counts" field is in 1/100ths of a second when this is on, so you can control how rapidly the code gets to the stoich region. Darren recently made some comments about tuning strategies in which he back calculated frequency from ignition events, and with this you don't need to do that, just set the time directly.

These run-time variables are switchable in some of the unused config bits (see below), rather than 'assemble-time' switchable through $IFs. See the settings.inc information in the tuning section for more info.

What You Need to Run the Dual Table Code

The Dual Table code runs on standard MegaSquirt® V1.01 or 2.2 hardware. Enabling some features will require you to recompile the dual table code with a suitably modified settings.inc file. However, to implement some of the features also requires using additional hardware to drive external devices.

For example, Eric Fahlgren has designed an 'expansion daugtherboard' for MegaSquirt® Version 2.2 hardware. Here is a schematic of the required daughter board that is needed for this feature:


Eric's daughter board provides IO expansion by adding two more ADC inputs, two binary inputs/interrupts and two high-current FET outputs. It is 'overdesigned' for most purposes, but it does work. It is designed to connect to a v2 board. The board's H1 and H2 headers plug right into MS V2.2 boards when the appropriate header pins are added to the MegaSquirt® board's already existing holes. It will fit in the MS case on top, and may even fit in below it if you're careful.

More details on the daughterboard are at:


However, all the addtional hardware you really need in most cases is to add a switching transistor onto the appropriate pin of the MC68HC908 for the desired function, so three parts are a minimal installation:

As mentioned above, enabling certain Dual Table features requires that you modify the values in the version 1.02 settings.inc file and recompile a .s19 file. Here is what the settings.inc file looks like:

** **
** These settings toggle behavioral changes. **
** **
$SETaseIgnCount; SET for ignition event count decay on ASE (B&G),
; SETNOT for seconds.
$SETegoIgnCount; SET for ignition event count on EGO correction (B&G),
; SETNOT for 0.01 sec time-based updates.
$SETidlIgnCount; SET for ignition event count on idle correction (BF),
; SETNOT for 0.01 sec time-based correction.
$SETNOTtaeIgnCount; SET for ignition event count decay on AE,
; SETNOT for 0.1 sec time-based (B&G).
$SETNOTinterpolatedPrime; SET for priming pulse interpolated from CLT,
; SETNOT for fixed value (B&G).
$SETNOThybridAlphaN; SETNOT for pure alpha-N mode (B&G),
; SET for Ferrari F40 hybrid alpha-N mode.
** **
** The following toggle the existence of code to implement the features. **
** Leaving things out makes the code smaller and faster. **
** **
$SETcrankingPW2; SET for bank1 and bank2 to both deliver fuel while cranking (B&G).
; SETNOT for bank1 only, probably water on bank2.
$SETNOTNitrous; Simple on-off nitrous control.
$SETNOTBoostControl; PWM boost controller using PD algorithm.
$SETNOTshiftLight; Assemble in the 3-stage shift light.
; These next two are mutually exclusive as the implementations both
; use portA sw1 on the daughter board. If one is SET, the other must
; be SETNOT!
$SETlaunchControl; Secondary rev limiter enabled via switch on sw1.
$SETNOTptaCounter; Put a tach input on sw1.

You can edit the settings.inc file with notepad. Generally, you enable a function by changing the $SETNOT in front of the applicable variable to $SET, and vice-versa to disable. Study the settings.inc file to better understand how this works. Recompiling with a modified settings.inc file is most easily done using the free WIN IDE 08 Integrated Development Environment (w/ Assembler) available at: www.pemicro.com

You have to register, but the program is free for use. See the WIN IDE help file for instruction on compiling the megasquirt_DT.asm file (and associated .inc files, etc.) into the .s19 file that you can upload to MegaSquirt.

Dual Table Code Source Files

The most recent dual table code files can be found at:


As well, the latest 'Download' program (a better alternative to hyperterminal for programming your MegaSquirt) can be found at:




This latest version of download.exe ignores blank lines and spits out comments to the console, and does not send them to MegaSquirt® EFI Controller, which has caused problems with some earlier versions.

To load the dual table code to MegaSquirt® EFI Controller, create a new clean directory for the Dual Table code files. Download the compressed file "megasquirt_dt.zip" from the above links or from the MegaSquirt msefi.com files section. Unzip the file into the directory, where it should create a couple of folders and then go from there.

The zip file includes all the files you need to compile the Dual Table code. There is also a 'pre-compiled' megasquirt_DT.S19 for direct loading (without compiling) to MegaSquirt® in the zip file as well, though it may not have the options you desire enabled. This .s19 file has the standard "Bowling & Grippo" defaults all turned on, so if that's what you want, you don't need to re-assemble the .asm file.

To enable other options requires you complie the megasquirt_DT.asm file with the appropriately modified settings.inc file. Then use download.exe to load the .s19 to MegaSquirt.

Tuning With the Dual Table Code and MegaTune

The dual table code was created to allow independent control of the two injector banks on MegaSquirt. You can emulate the standard MegaSquirt® simultaneous mode quite easily by driving both banks from table 1 and enabling gammae on both, but by doing so you are adding untested complexity to get what the B&G code already delivers.

On the front page of MegaTune, there is a little 'spinner' at the bottom showing P1 or P2 (see above). P1 is for injector bank #1, P2 for injector bank #2. You can also switch between the two banks by hitting Alt-X (where X is 1 or 2), then 'fetch' the new values. Make sure you have MegaTune 2.13 or higher, as previous releases of MegaTune do not fully support the Dual Table code. Note that there is no other indication of which table your are modifying, so be careful!

Also it is VERY IMPORTANT to note that dual table mode provides separate values for EVERY constant for each bank. You have different Req_Fuel values for each bank, etc. One small shortcoming in current MegaTune versions is that you cannot readily distinguish which "page" you are working on when you viewing a constants dialog, so be careful.

The dual table code requires some extra control that makes the original alternating/simultaneous squirt option obsolete, so Eric has changed that option menu to a button called "Table Use" (see above). The button pops up a dialog (see below) that allows you to control which table drives which injector, etc. You can select either injector to be driven by either table, and can enable or disable all the 'gamma' corrections for either channel, too.

For example, Eric's configuration is set to deliver fuel with bank 1, running from table 1 and has all the enrichments turned on for that bank. Bank 2 is a water injector, driven from table 2 with no enrichments. This means that his fuel delivery is computed and pulsed on bank 1, just like any other MegaSquirt. Bank 1 uses the full B&G pulsewidth calculations including all the warmups and acceleration enrichments and EGO correction, and so on. Bank 2, on the other hand, does not have any gamma corrections (enrichments). Only the applicable VE table value (based on MAP and RPM) is used to determine the pulsewidth for bank 2. It might be -40F or 90F outside, but the calculated pulewidth for bank 2 won't change.

Note that the Dual Table code maintains the PWM (if set) so you can use either high or low impedance injectors on either bank (as long as all injectors on one bank are the same, any combination is possible). For example, Eric runs 5 hi-impedance injectors on bank 1 and 1 low-impedance injector on bank 2. Be sure to 'tune' your PWM settings for any bank that uses low-impedance injectors. The tuning process is described in the MegaManual.

The Dual Table code supports Alpha-N control algorithm on one injector bank and Speed-Density on the other. You can choose either algorithm for either bank, mix and match as you see fit.

Eric even went as far as to work out the code for a blend function, see:


There is a switch in the Dual Table code so you can make alpha-N work as described in #2 of the above document, just like a Ferrari F40!

To start your tuning with the Dual Table code, first set the rev limit to an appropriate value for your engine. Go to Tools->Table Editor and turn on Decimal mode. Look at the value at the intersection of $F0 row and the $0B column and you'll see that the value is 67 (decimal, since the 'Dec' radio button is 'clicked'), so the current revlimit is set at 67*100=6700.

You can change the rev limit to any other value, Burn it to MegaSquirt® EFI Controller, and you have reset the rev limit. Put in a value from 0 to 255 (decimal), which will be the rev limit (divided by 100). For example, if you type in 105 at location $FB in the table, and you set the rev limit to 10,500 rpm. Be sure to save your config so you have a baseline. If you want to disable the rev-limit feature, use a value of 0 (zero) at $FB.

There is also a variable to define the cranking RPM, it's at $FF (the intersection of $F0 and $0F). This may be especially useful to those with small displacement engines, which probably crank well above 300 RPM.

You may notice some apparently strange behavior on the stimulator when you first load the Dual Table code. The 2nd injectors LED will not come on. Neither will the Fast Idle LED. If you have dual table mode set, and zeros in all the bank 2 VE table (the default), then you'll see exactly that. Go to the constants screen and make sure you either have Dual Table mode turned off, or have bank 2 driven from an appropriate VE table.

You may not see the idle solenoid led on your stim light up if the PWM idle mode is enabled. To see it work, you'll need to crank the RPMs down low and wait for the duty cycle to go up enough to light the LED. If you are using MegaTune 2.15 or higher, the PWM duty cycle on the runtime screen was changed to Idle DC.

You can turn off PWM idle by setting bit 5 of config13 to zero. Config13 lives at $76 in the table editor (see below). To enable PWM idle control and set the desired idle RPM and fast rpm, there is the 'Brian/B&G' bit in config13/bit 4 ($10 or $00 at $76 in the table editor). From the DT 1.01 def file:

The standard B&G code has 128 bytes of memory holding the constants, enrichments tables and VE table. In the Dual Table code, this 128 byte chunk is doubled up, with most (but not all!) of the entries in the second copy being used. Most notably, the injector characteristics, engine settings (nCyls, nInjectors and so on) are separate.

Note: Regardless of whether you are using Dual Table mode or not, you must set up the Constants screen for both banks, even if the injectors on the banks are identical.

The VE Tables are layed out as with the standard MegaSquirt® embedded code, but there are two of them, one for each injector bank. The top row on the numeric editor page is low MAP values proceeding from low RPM on the left to high RPM on the right, MAP values ascend as you go down the page.

In Tools->Table Editor, you see all 256 bytes of both "tables" with the VE tables starting at $00 and $80. If you look in the listing file, megasquirt_DT.lst, included with the Dual Table zip file, you will find all the various bits and pieces in their absolute locations (say, look for "REVLIMIT" which is at $0199 in Eric's development version) in the symbol table dump at the bottom of the file.

In the Dual Table version 1.02 release, there is a new file called "offsets" that gives a memory map of all the variables in both tables. This eases locating variables in the table editor considerably, since they are all there and all in order.

To translate these absolute locations into zero-based table addresses, just subtract the value of VE ($009E in the dev code) to get the table offset, which for REVLIMIT is $199-$9E = $FB (use the Windows calculator [Programs/Accessories/Calculator] in hex mode to help with the hexadecimal calculations).

config13 bits = {
oddFire [0] = 0
wideBand [1] = 0
alphaN [2] = 0
baroCorrection [3] = 0
pwmIdle [4] = 1

The other Dual Table configuration values are at these locations in the table editor:

$79 - fastIdleTemp byte = 125T ; Fast Idle Temperature, F
$7c - slowIdleTemp byte = 185T ; Slow Idle Temperature, F
$7d - fastIdle byte = 110T ; Fast Idle Speed, RPM/10
$7e - slowIdle byte = 65T ; Slow Idle Speed, RPM/10
$7f - idleThresh byte = 30T ; TPS A/D count threshold below which idle is on.

If you turn on decimal display in the table editor, you should see the above values 185...30 as the last four entries in the $70 row. Note that the idle speeds are RPM/10 for fastIdle and slowIdle, not RPM/100 as elsewhere in the code. To get the idleThresh ADC count, use the throttle calibration dialog to find your idle ADC count and add a couple ticks to it.

In setting the constants for the Dual Table code, you need to carefully consider your configuration and usage. For example, when using the Dual table code with water injection on the second bank, you may want to make the constants for table 2 identical to table 1, with the exception that Req_Fuel for the injector is set to match the water injector. This will make it very easy to know exact proportions of fuel versus water. Remember that water is about 1.3 times as dense as fuel, so make Req_Fuel for the water the petrol value * 0.75 to get the same mass flow.

On the other hand, you might make up an Req_Fuel value that gives the same mass flow as the fuel injectors:

ReqFuel_WI = 0.75 * ReqFuel_FI * flow_FI / flow_WI

If you do this, then the same VE table values will give you the same mass flow on a fuel injector and a water injector.

If you want water injection activated at 170kpa (~10psi) set the VE at 1% at 170, zero below that, and whatever you calculate for higher MAP values. You need to lean out the AFR (from the non-water injected values) as the water/methanol comes on. So if you are running 14.2:1 petrol (if you've got the fuel mapped without water already to give 12.5 then just change the VE entries to 12.5/14.2 of their current value to get 14.2), then you can inject about 25% water by mass (if you have one water injector and four fuel injectors, just set the VE tables the same when you want 25% water).

Other applications of the Dual Table code require lots of careful thinking before running. Be sure YOU understand what you are trying to accomplish, and how the Dual Table code will help, you before using it!

MegaSquirt® and MicroSquirt® controllers are experimental devices intended for educational purposes.
MegaSquirt® and MicroSquirt® controllers are not for sale or use on pollution controlled vehicles. Check the laws that apply in your locality to determine if using a MegaSquirt® or MicroSquirt® controller is legal for your application.
©2004, 2005 Eric Fahlgren . All rights reserved. MegaSquirt® and MicroSquirt® are registered trademarks.