Programming 101 Information Repository/CSH suppository
The purpose of the Programming 101 project is to analyze OEM fuel and ignition management issues. To this end, some members of the DIY_EFI list are focusing on the GM 1227747 ECM. This ECM is a TBI controller, used in 6/8 cylinder GM trucks and 6 cylinder Astro vans from 87-91. The goal is to understand the location and purpose of all the tables in the EPROM. Once this is accomplished the knowledge can be applied to other GM ECMs. The information on this page is also in the archives, and can be retrieved by doing a subject line search for "Programming 101".
This is for educational purposes. Changing the calibrations of your ecm may violate the laws in your area. If you attempt recalibrations, serious engine damage may result. Please read past posts about tune up procedures, when attempting recalibrations. These matters should be done under adult supervision. Again this is in general for GM ecms, and most specifically the 1227747.
The '747 ECM uses a socketed PROM and a soldered ROM. The PROM has tables and some program code. It maps into processor space from 0xd000 to 0xdfff. The ROM appears in the processor space from 0xe000 to 0xffff. Data space in the PROM is from 0x000 to 0x616. Code starts at 0x617 and continues to the end of the PROM, 0xfff.
The '747 ECM uses a GM specific derivative of the Motorola 6809.
Summary of tables and their locations in the EPROM:
Address Range | Purpose |
0x00-0x004 | Checksum and PROM ID |
0x035-0x106 | Spark table (14x15) |
0x15e-0x165 | WOT Spark adder |
0x17f-0x187 | Knock sensor retard at WOT |
0x188-0x18c | Knock sensor retard non WOT |
0x30e-0x312 | Delta MAP enrich |
0x314-0x31d | TPS enrichment |
0x31e-0x323 | quan enr |
0x37f-0x3c6 | Fuel table (9x8) |
0x3c7-0x3d7 | VE after |
0x44a-0x458 | Cranking fuel vs temp |
0x459-0x468 | AFR vs temp |
0x47d-0x485 | Percent of TPS to enable PE |
0x50d-0x50f | Malfunction flags |
0x5f5-0x605 | Idle fuel vs temp |
0x60e-0x616 | Idle speed temperature corrections |
Units
All these tables are used in a similar fashion. You index into the table using one or two values (MAP, RPM, temp, etc.), and retrieve the value stored there. The table indices are fixed by the coding in the ECM, but what about the value stored in the table? How is the value there converted to a real world number representing spark angle, volumetric efficiency, etc? See the table below. In this table, "X" represents the value retrieved from the table.
Type of data | Calculation | Units |
temp | X*191/255-40 | degrees C |
Speed | no calculation | 0-255 MPH |
Rev limiter | X*25 | RPM |
Idle RPM | X*12.5 (0-3187, most common) or X*25 (0-6375) |
RPM |
WOT AFR | X*100/256 | % change in calculated AFR for WOT |
PE (power enrich) | X/10, or (X-128)/128*100 |
X/10 gives absolute AFR, the other formula gives a % change from -100 to +100. |
VE (volumetric efficiency) | X/256*100 | 0-100% |
Knock retard | X*45/256 | 0-45 degrees |
Knock attach | X*.0225 | milliseconds |
Knock recovery | X*500/256 | milliseconds |
Spark Advance | X*90/256 | 0-90 degrees |
For example, if you looked in the knock retard table, you might find the value 0x44 (hex, or 68 decimal). What's that mean in real world units? According to the table above (Knock retard), you take the table value, multiply by 45 and divide by 256, which gives 11.9. That's almost 12 degrees of retard when knock is detected.
Pressure Conversions
Here is a table for converting between pressure units. kPa and PSI are in absolute pressure, in-hg is in gauge pressure as you would see it on a vacuum gauge.
kPa | PSI | in-hg | kPa | PSI | in-hg | |
5 | .725 | 28.5 | 55 | 7.98 | 13.8 | |
10 | 1.45 | 27.0 | 60 | 8.70 | 12.3 | |
15 | 2.17 | 25.6 | 65 | 9.43 | 10.8 | |
20 | 2.90 | 24.1 | 70 | 10.2 | 9.33 | |
25 | 3.63 | 22.6 | 75 | 10.9 | 7.87 | |
30 | 4.35 | 21.1 | 80 | 11.6 | 6.45 | |
35 | 5.08 | 19.7 | 85 | 12.3 | 5.03 | |
40 | 5.80 | 18.2 | 90 | 13.1 | 3.41 | |
45 | 6.53 | 16.7 | 95 | 13.8 | 1.95 | |
50 | 7.25 | 15.2 | 100 | 14.5 | 0.470 |
Address | Purpose |
0x000 to 0x001 | Checksum |
0x002 to x003 | Chip ID |
0x004 | Enable checksum |
To calculate the checksum, add all bytes in the PROM, starting immediately after the Checksum word itself. Truncate the result to 16 bits (4 hex digits). The result is the checksum. For example, add all bytes starting at offset 0x002 and continuing to the end (0xfff). Lets say the result is 72,182 decimal, or 0x119f6. Truncating the result to 4 hex digits results in 0x19f6, which is the checksum. Location 4 is the enable checksum flag. If the value 0xaa is stored here then the ECM does not perform a checksum test on the PROM image. This value and location is specific to the 7747 ECM, it may not be the same for others.
Memory Location | Purpose |
0x35 to 0x106 | Spark advance table |
This table is organized as a 14 row by 15 column table. It appears in memory as row 0, followed by row 1, etc. The rows are RPM, and the columns are manifold pressure in kPa. Here is an example from a non-factory EPROM:
Pressure (kPa)
30 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 | 100 | |
400 | 0 | 0 | 0 | 0 | 0 | 12 | 16 | 16 | 16 | 12 | 8 | 8 | 8 | 8 | 8 |
600 | 0 | 0 | 0 | 0 | 0 | 12 | 16 | 16 | 16 | 12 | 8 | 8 | 8 | 8 | 8 |
800 | -4 | -4 | -4 | -4 | -2 | 12 | 16 | 16 | 16 | 12 | 8 | 6 | 4 | 4 | 4 |
1000 | -6 | -6 | -6 | -4 | 0 | 12 | 12 | 12 | 11 | 8 | 6 | 4 | 4 | 4 | 4 |
1200 | -6 | -6 | -6 | 8 | 10 | 14 | 14 | 12 | 11 | 8 | 6 | 4 | 4 | 4 | 4 |
1400 | -6 | -6 | 18 | 20 | 20 | 18 | 14 | 12 | 11 | 8 | 6 | 4 | 4 | 4 | 4 |
1600 | -6 | -6 | 24 | 24 | 20 | 18 | 14 | 12 | 10 | 8 | 8 | 8 | 6 | 6 | 6 |
1800 | -6 | -1 | 27 | 28 | 24 | 22 | 17 | 12 | 10 | 8 | 8 | 8 | 8 | 6 | 6 |
2000 | -6 | -1 | 30 | 30 | 26 | 22 | 16 | 12 | 12 | 10 | 8 | 8 | 8 | 8 | 6 |
2200 | -6 | -1 | 30 | 30 | 26 | 22 | 18 | 16 | 14 | 12 | 10 | 11 | 8 | 8 | 6 |
2400 | -6 | -1 | 30 | 30 | 26 | 22 | 18 | 16 | 14 | 12 | 12 | 12 | 10 | 10 | 10 |
2800 | 0 | 0 | 26 | 26 | 26 | 22 | 22 | 18 | 18 | 17 | 16 | 14 | 14 | 14 | 14 |
3200 | 0 | 0 | 24 | 24 | 24 | 22 | 22 | 20 | 18 | 18 | 18 | 18 | 16 | 17 | 17 |
3600 | 0 | 0 | 22 | 22 | 22 | 22 | 20 | 20 | 20 | 18 | 18 | 18 | 16 | 16 | 16 |
Please don't burn this table into your EPROM. This is for a fairly hotrodded engine, aluminum heads. See the tuning tips link for the details.
Memory locations | Purpose |
0x17f to 0x187 | WOT retard |
0x188 to 0x18c | non WOT retard |
The WOT table is by RPM, the other table appears to be MAP related. A good value for all entries would be 0x44, or 68 decimal. The value to store in the table is the retard in degrees, multiplied by 255 and divided by 45. For 12 degrees of knock retard: (12*255)/45=68, or 0x44.
Memory locations | Purpose |
0x15e to 0x165 | Timing advance WOT |
0x3C7 to 0x3d7 | Fuel enrichment WOT |
This table specifies spark advance and fuel enrichment at WOT throttle conditions. When modifying remember that it's better to start with too much fuel and too little spark, and slowly sneak up on better values.
Memory locations | Purpose |
0x37f-0x3c6 | Fuel table |
This is the main fuel delivery table. It is a two dimensional table, with RPM on one axis and MAP on the other axis. The value in the table is volumetric efficiency, which is used in the fuel calculation to determine the injector pulse width. Volumetric efficiency is expressed as a percentage. It's the theoretical amount of air that the engine should be pumping (depends only on RPM) divided by the actual amount of air that the engine is pumping (it's less than theoretical due to the throttle plates and other intake restrictions). Here is a sample table. Again, it is from a somewhat hot-rodded engine, so please don't just burn it to your PROM.
MAP
20 | 30 | 40 | 50 | 60 | 70 | 80 | 90 | 100 | |
400 | 0 | 0 | 0 | 16 | 16 | 36 | 41 | 50 | 54 |
800 | 0 | 0 | 0 | 16 | 18 | 39 | 47 | 52 | 54 |
1200 | 0 | 0 | 0 | 29 | 45 | 50 | 52 | 57 | 60 |
1600 | 0 | 0 | 25 | 46 | 50 | 51 | 54 | 58 | 60 |
2000 | 0 | 0 | 51 | 49 | 51 | 53 | 57 | 59 | 62 |
2400 | 0 | 1 | 49 | 49 | 51 | 54 | 56 | 59 | 62 |
2800 | 0 | 2 | 50 | 52 | 54 | 55 | 57 | 60 | 64 |
3200 | 0 | 3 | 50 | 53 | 55 | 57 | 59 | 61 | 64 |
Address | 0x50d | 0x50e | 0x50f | |||||||||||||||||||||
Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
Trouble code | 12 | 13 | 14 | 15 | 21 | 22 | 23 | 24 | 25 | 31 | 32 | 33 | 34 | 35 | 41 | 42 | 43 | 44 | 45 | 51 | 52 | 53 | 54 | 55 |
This table specifies which diagnostic codes are enabled, and which are disabled. Disabling a code does not necessarily turn off the corresponding test. It does prevent a failure code from being stored, prevents the check engine light from coming on, and prevents "limp home mode" if a failure of the particular test would otherwise cause "limp home mode". Each address has an 8 bit value stored, and each bit controls a particular diagnostic code. Bits are numbered with 0 being the least significant bit, and 7 being the most significant. An example? Lets say address 0x50f has the value 0xfc. 0xfc is 1111 1100 in binary. The two zeros are in the least significant places, so that means codes 54 and 55 are disabled. Any service manual can tell you what the meaning of the various error codes is.
Address | Purpose |
0x44a to 0x458 | Cranking fuel vs temp |
Address | Purpose |
0x5f5 to 0x605 | Idle fuel vs temp |
Address | Purpose |
0x47d to 0x485 | Percent of TPS to enable PE |
TPS is throttle position sensor. It tells the ECM how far open the throttle is. PE is power enrichment. When the ECM is in PE mode, it advances the spark some and adds extra fuel for more power. This table tells the ECM when to enter PE mode, based on the TPS.
Idle speed temperature corrections
Address | Purpose |
0x60e to 0x616 | Idle speed temperature correction |
Corrects idle speed based on engine temperature.
Address | Purpose |
0x459 to 0x468 | AFR/temp corrections |
This table details corrections to the A/F ratio, based on engine temperature. It includes startup enrichment (choke).
Address | Purpose |
0x30e to 0x312 | Delta MAP enrich |
0x314 to 0x31d | Delta TPS enrich |
0x31e to 0x323 | Quantity enrich |
The '747 EFI system, being a TBI system, needs to emulate the accelerator pump found on carbed engines. The accelerator pump on a carb injects a squirt of fuel into the manifold when the throttle is opened quickly. There are three reasons for this extra fuel:
1) The sudden opening of the throttle lets in more air, which the venturies can't immediately respond to.
2) The sudden opening of the throttle increases the absolute pressure in the manifold, which can cause some of the vaporized gas to condense into a liquid on the manifold walls.
3) At WOT you want more fuel anyway to make the most power.
The '747 ECM uses these 3 tables to emulate the accelerator pump function. Delta MAP refers to the change in MAP versus time. A large Delta MAP indicates a large change in MAP over a small period of time, and a need for an extra squirt to make up for the fuel that condenses onto the manifold walls. Similarly a large delta TPS indicates a large change in throttle position over a small period of time, and the need for extra fuel.