This page describes my ongoing project to convert my Fury from distributor ignition and carburettor fueling to full engine management, with electronically controlled ignition timing and fuel injection.
Rather than do this the easiest and expensive way (by buying an aftermarket engine management system, special manifold, and throttle bodies - adding up to thousands of pounds), I have chosen to adapt an engine management system that used to be fitted to productions cars made by General Motors in America, and plan to use that in conjunction with a cheap approach to inlet manifold and throttle bodies (details to be added later). GM don't make these any more. Mine came out of an american scrapyard quite a few years ago now.
In order to perform optimally (i.e. provide an acceptable compromise of good: power, economy, and longevity) an engine needs to be supplied with different ignition timing and fuel quantities to meet its exact needs at any instant in time. This is best achieved by controlling these inputs using a computer. In order to estimate what the engine needs, the main things that the engine management computer needs to know are: what the engine speed (RPM) is and how hard the engine is required to work (known as: load). This information is supplied to it by sensors, attached to the engine.
Engine speed can be measured directly. Engine load is more illusive and there are different ways of estimating it, which I will talk about later. By experimentation (e.g. using a rolling road or wideband lambda probe) optimum ignition timing and fuel quantity can be determined, for a given engine, under all speed and load conditions. These are then stored in 'look-up' tables in the memory of the engine management computer. When the engine is running, thousands of times a second, the computer takes measurements from the speed and load sensors and uses these, in conjunction with other sensor measurements, to look up the best ignition timing and fuel quantity to supply to the engine, at that moment.
I am currently using a scrap american engine management computer (GMECM) with part number 16149396. This is a 'P4 generation' ECM and is identical to the common (and better documented) 1227727, except that the 16149396 has additional SRAM (which makes it much more useful). According to this site, the 16149396 was used from 1991 to 1994 in 3.1 and 3.4 litre V6 engined Buick and Pontiac cars, whereas the 1227727 was used in cars powered by 3.4 litre V6 and 5.7 V8 engines (including the Chevrolet Corvette). All the P4 generation units have, at their heart, a micro-controller which is based on the Motorola 68HC11. The fact that the 16149396 was fitted to 3.1 and 3.4 litre V6 engines is irrelevant to its reuse - it's the software that really matters (see next section). There is only one tiny change required to the (MemCal) hardware to make the whole ECM run happily on a 4 cylinder engine.
The ECM case is designed for engine bay ("under hood") use, consequently it is waterproof - which is pretty handy.
The table below shows pictures of the ECM and some of its peripheral sensors.
| Outside ECM - waterproof case | Inside ECM - circuit board and MemCal | MemCal |
| GM HEI module | GM/Vauxhall MAP sensor | GM (not Vauxhall) CTS |
| Emerald (RS) TPS | My DIY IAT sensor | Vauxhall XE CTS |
The GMECM software 'code' and look-up tables 'calibration data' all reside on a single EPROM. In the case of the 16149396, this is a 32K x 8 bit (27C256) 'chip', but other GMECMs use 16K x 8 bit (27C128) EPROMS. The software is written in the native assembly language of the 68HC11 micro-controller. This makes it much faster and more space efficient than if it had been written in a high level language, such as 'C', and cross-compiled. A sample of GM 68HC11 assembly language can be seen below:
F5E6: LF5E6 SUBA 0,X F5E8: PSHB F5E9: PSHX F5EA: BCC LF5ED F5EC: CLRA F5ED: LF5ED SUBB 1,X F5EF: BCC LF5F2 F5F1: CLRB F5F2: LF5F2 PSHB F5F3: LDAB #$10 F5F5: MUL F5F6: PSHB F5F7: LDAB 2,X F5F9: PSHB F5FA: MUL F5FB: ABX F5FC: INX F5FD: INX F5FE: INX F5FF: PSHX F600: TSX F601: LDAA 4,X F603: LDX 0,X F605: JSR LF5BC F608: PSHA F609: TSX F60A: LDAA 5,X F60C: LDAB 4,X F60E: STAB 5,X F610: LDAB 3,X F612: LDX 1,X F614: ABX F615: JSR LF5BC F618: TAB F619: PULA F61A: PULX F61B: PULX F61C: JSR LF5CC F61F: INS F620: PULX F621: PULB F622: RTS
The above is actually the table look-up routine from the software that I'm currently using - and consequently vital to the operation of the ECM.
GM designed different software to run on fundamentally the same hardware. The format of the calibration data also varies across different applications. Even if exactly the same software and calibration data format is used for two different engines, the actual calibration data values will be different - because they are engine specific.
Don't read this paragraph unless you really care about how GM identified EPROM contents! GM used two different identifiers in relation to the software variant, calibration data format, and the specific calibration data values. One is a hexidecimal representation of an 8 bit number (e.g. $8D, $58), which is stored in the calibration data of the EPROM (9th byte in my experience). The other is a 4 letter name (e.g. ANHT, AYBN), which is printed on a label on the outside of the EPROM and is unique for each application. The 4 letter name uniquely identifies the whole chip contents, including tuning data for its specific application. For a given 4 letter name, the hexadecimal number will always be the same inside (i.e. ANHT always has $8D inside and AYBN always has $58 inside). However, there isn't a unique mapping the other way - e.g. ANHT and AUJP both have $8D inside. I'm told by the mega GMECM gurus that the hexadecimal identifier refers to the format of the calibration data, rather than the software variant, and hence two different software variants could use the same calibration data format. However, it's obvious that one software variant couldn't use two different calibration data formats because the software has to know the format of the calibration data in order to read it correctly. What the gurus say may be true but I have not seen two software variants use the same calibration data format hence, as far as I'm concerned, the hexadecimal representation refers to the software variant and hence also uniquely identifies the format of the calibration data. It definitely does not refer to the (application) specific calibration data values.
As you might expect, there's a reasonable amount of similarity between all the software versions - so lessons learned from 'hacking' one version can usually be applicable to the version that you're using (and hacking!). As the micro-controller is based on a Motorola 68HC11, the freely available disassemblers and assemblers for this processor can be used.
GMECM software uses many many look-up tables, arrays, and values that combine as adjustment upon adjustment to fine tune ignition timing and fuel quantity (far far more than aftermarket ECUs). Getting these set correctly is one of the major challenges of using it.
Some versions of GMECM software are configured for throttle body injection (TBI), and some are configured for port fuel injection (PFI). I believe both were used in the original GM cars in conjunction with a single throttle butterfly. In TBI, the fuel is injected upstream of the throttle butterfly (before inlet tract is split up into branches for each cylinder); whereas in PFI it is injected downstream of it. TBI uses only a single (vert high flow) injector, but PFI uses one injector per cylinder (which can be 4, 6, or 8). However, all these injectors are fired simultaneously as there is usually only one injector driver circuit in the hardware. Consequently sequential fuel injection is not an option.
For the first few years that I used a GMECM - just to control my engine's ignition - I adapted and ran with the $8D software. This was because one of its applications (a V8 Chevrolet Corvette of the early 90's) has probably the most commented, freely available hack, and it's designed for PFI - which is what I want for fuel injection. The specific application chip name is 'ANHT'. Despite the fact that this variant of the software was originally used for a V8, GM provided the ability for it to be very easily configured in to work for a 4 cylinder engine. The complete contents of a chip can be stored on a PC as a binary file. A binary file, containing the whole of the original ANHT EPROM can be downloaded by clicking here, and a disassembled 'hack', created by 'ECMGuy', can be found as a .PDF file here.
However, despite being well hacked, ANHT/$8D is one of the most complex GM software versions (using almost the full 32k EPROM space) and its look-up quantities are not as well understood (by the hacking community) as those for the software used in the 1987-1990 Pontiac Sunbird 2.0 4 cylinder Turbo and the 1991-1993 GMC Syclone/Typhoon V6 'trucks'). These both use the identifier '$58'. Consequently, since I am preparing to adapt my engine installation for fuel injection, I decided to change to software whose tuning data was better understood, to save myself many many hours of hacking and testing (this project had already taken hundreds of hours of my time...). The Sunbird software (as I shall call it, from now on) still has many many adjustments, though, as can be seen by clicking here. A binary file, containing the whole of the original Sunbird EPROM can be downloaded by clicking here. It's also designed for PFI.
The Sunbird software originally ran on 1227749 hardware, which used a 16K x 8bit (27C128) EPROM. GM never installed it on my particular variant of ECM hardware - or the more common 1227727 - although there is a very great deal of similarity between the two. This has made my life a little more difficult! The most fundamental thing that has to be done to run this software on my hardware is to load it into the higher (bottom) 16k of the 27C256. However, this is not all; the Sunbird software uses different registers from ANHT to control certain functions, so some ECM pins change function. This renders the (well documented) Corvette ECM wiring diagrams partially invalid (with the 'partial' bit ill-defined!)
For my engine, another undesirable aspect of the Sunbird software is that its look-up values are configured for a turbo application, using a 2 bar Manifold Absolute Pressure (MAP) sensor. Fortunately, for some (happy) reason, GM gave the software the option to run with a 1 bar MAP sensor (like the one I have - which is optimal for a naturally aspirated engine). However, there are a number of look-up values which are set for a 2 bar sensor and require changing to ensure correct operation with a 1 bar sensor.
Despite the above, I seem to have the Sunbird software running my engine's ignition with no obvious problems, and, after a bit of ignition table tuning, and one GM 'bug' fix, my engine is pulling better than ever before. :-)
Whilst, as previously mentioned, the 16149396 hardware has just one injector driver circuit - so all the injectors are driven from this - the Sunbird software supports three individual firing schemes: 'synchronous', 'quasi-asynchronous' and 'asynchronous', which work together to give the engine the fuel it needs under all conditions. In pure synchronous mode, the injectors are normally 'fired' every crank revolution; but, if the injector pulse width is very short (e.g. < 1ms), synchronous mode is replaced by quasi-asynchronous mode - which fires the injectors every 2 crank revolutions - and for twice the computed pulse width. Additionally, (fully) asynchronous injector pulses augment synchronous pulses to provide extra fuel under certain conditions.
The software determines the basic amount of ignition advance to apply to the engine by using a look-up table. On one axis of the table is the engine speed (RPM), sensed by the distributor (which must not apply any ignition advance itself, other than a small static amount via its mounting angle). On the other axis is engine load. Engine load measurements are provided by an inlet MAP sensor which, in my application, is connected to all four inlet tracts, via the carburettor, by vacuum hose. Use of MAP based engine load in conjunction with engine speed to determine engine conditions is known as 'Speed-density' (although the term is normally used to describe the way that MAP measurements are used to compute the correct amount of fuel to add, based on the ideal gas law). For a naturally aspirated engine, MAP never exceeds atmospheric pressure (~100kPa, or 1 bar). Most of the time the pressure is less than this, so there is actually a vacuum in the inlet manifold.
The main $58/Sunbird ignition advance table has lookup RPM values from 600 to 4800 RPM. This is fine as, for most engines, ignition advance does not need to increase for higher RPM. By logging the lookup ignition advance value in conjunction with RPM and MAP, I verified that I have successively disabled other ignition advance modifications by overlaying these ignition advance values over my intended ignition advance lookup table in a MatLab plot. In the plot, the black points are the logged ignition advance values. You can see that I've revved the engine well past 4800 during the journey and the ECM code has successfully applied the 4800 RPM values.
The cylinder trigger sensor in the distributor is directly connected to a remote GM ignition module (HEI). The HEI requires a trigger signal from a reluctor sensor. (Unfortunately, no reluctor sensor based distributor that fits my engine was fitted to UK GM cars, so I had to fit the reluctor sensor from one Vauxhall distributor into the casing from a different type. I also had to have the advance mechanism welded up to stop the distributor from applying ignition advance itself.) The HEI is connected to the ECM, and so the ECM knows the engine speed and position of the engine relative to the next cylinder firing event. The HEI is also connected to the coil, which is connected to the distributor cap and hence to the spark plugs. According to the spark timing, the ECM tells the HEI to dump the coil, and the appropriate plug is fired, due to the alignment of the rotor arm and the internal reluctor sensor in the distributor. It is necessary to make sure that the distributor itself doesn't apply any advance via its internal weights and vacuum. The best way to stop the weights from applying advance is to weld them up (as mentioned above). Simple disconnection of the vacuum hose to the diaphragm is enough to disable the vacuum advance. In my case, I disconnected the hose from the distributor vacuum advance unit and connected it to the MAP sensor, instead.
The GMECM software uses a Throttle Position Sensor (TPS) for small corrections to the base map, such as when you plant the throttle - when more ignition advance and fuel are beneficial. There are many other corrections/modifications to the main ignition, depending on what is going on...
MAP sensor based GMECMs use the Speed-Density system to determine the amount of fuel to inject into the engine. In this system, the basic mass of fuel to inject is computed to provide a specific air/fuel ratio - based on the computed mass of air entering the engine at any given time. The air mass is computed from the ideal gas law:
PV = nRT
In its application of the ideal gas law the GMECM uses: pressure measurements from the MAP sensor, temperature measurements from the MAT sensor, and volume based on actual cylinder capacity (provided as a configuration input value) - modified by a volumetric efficiency (VE) look-up table (which is engine hardware specific). Like the main ignition lookup table, on one axis of the VE table is the engine speed (RPM), and on the other axis is engine load.
Since fuel is provided by fuel injectors, which are designed to flow fuel at a fixed rate (subject to hardware configuration), the final step in the GMECM's basic fuel calculation is to compute how long to turn on the injectors in order to provide the calculated fuel mass. It does this using the injector flow rate - which is another configuration input value. The result is called the [injector] base pulse width. A number of other factors can then (optionally) be taken into account to compute the final width, but I am not going to describe them here.
The main $58/Sunbird VE table has lookup RPM values from 800 to 4000 RPM. This might have been fine for a low revving turbo engine but my engine is naturally aspirated and (with appropriate induction hardware) will generate increasing power up to ~6500 RPM. The $58/Sunbird has a second VE table stored right after this one, intended for closed-throttle (only) use. Taking the idea from the $59 (yes 59) community, I modified the code to replace the two afore-mentioned tables with a single one, having RPM extend up to 6400. At the same time I fixed a bug in the GM code which was causing the VE value on the data stream to jump about. By logging the lookup VE value in conjunction with RPM and MAP, I verified my code change by overlaying these VE values over my intended VE lookup table in a MatLab plot. In the plot, the black points are the logged VE values.
I have worked through the Sunbird injector pulse width calculation in the software. This led me to discover that one of the fixed lookup arrays, used to speed up the computation, was populated with values which did not match what the mathematics clearly showed should be there. I believe this was a tweak by GM due to the Turbo used in the Sunbird so, since my engine is naturally aspirated. I have repopulated the array with mathematically correct values. There are plenty of other places to 'tweak'.
In order to prove I have mastery over the settings in my (Sunbird) GMECM configuration, I have retrospectively calculated injector pulse width from the relevant physical quantities and measurements (captured from the sensors through data logging), using the ideal gas law, and achieved a very close match the GMECM computed values (also captured through data logging) throughout multiple long car journeys. I have also externally duplicated the GMECM calculation steps. Given that the GMECM calculation is not being done in floating point arithmetic, and that the MAP values are so noisy, the level of agreement observed is excellent - giving me full confidence that the GMECM is doing exactly what I want it to do.
GMECM software (in conjunction with its hardware) has other good features; it can control up to two fans, provide an upshift light, and can control the EFi pump. So far I have used the first two of these and plan to use the third when I implement fuel injection. The beauty about fan control is that you aren't at the mercy of off-the-shelf fan switches; you can set the exact ON and OFF temperatures that you desire (and make it very accurate by fine tuning the calibration of the CTS sensor used in the ECM, if you're as geeky as me!). The shift light feature avoids having to buy and install additional hardware; and the EFi pump control (which turns the pump off if the engine stops - for whatever reason) provides an element of safety in the event of a crash.
I've also written software to display engine parameters on a PDA which I fit to the inside of the windscreen. This is to reduce the likelihood of me driving on the wrong side of the road - as I sometimes found myself doing when trying to read the screen of the lap-top (located in the passenger seat)!
Engine management systems that use the 'Alpha-N' system, to determine the amount of fuel to inject in the engine, do not calculate the amount of fuel, they simply use a value from a look-up table where engine load is determined by throttle position (via the TPS). Typically, this look-up table provides the injector pulse width directly. This is a compromise, for the following reasons:
(1) As an engine is effectively just an air pump, and air obeys the ideal gas law, the amount of air that the engine draws in (and therefore the power that it produces) is a direct function of the air pressure (MAP). The throttle is the indirect means by which the driver controls the power produced by the engine, by its affect on the MAP, and this affect changes when atmospheric pressure - or any part of the engine's induction or exhaust system - changes (either by deliberate modification, or wear and tear). The most significant short term change is atmospheric pressure. Alpha-N systems go out of calibration when the atmospheric pressure differs from that on the day when they were mapped. This is particularly a problem when driving at higher altitudes. In this situation, the Alpha-N system does not know that atmospheric pressure has changed (unless it is supplemented by a barometric sensor - but even then this provides a crude correction mechanism). Consequently, the accuracy of the mapped relationship between throttle position and MAP is reduced, resulting in the wrong look-up table values being used - therefore the engine runs sub-optimally.
(2) With Alpha-N, if the TPS is rotated at all, or changed for one with different calibration, then all the look-up values based on it will be in error. MAP sensors have no such alignment problems (and are much easier to fit than a TPS!)
(3) Changes in throttle position can control MAP only upto the point where opening the throttle further doesn't make any difference. Let's call this the throttle position threshold. (You can experience this easily just by driving: Starting from lowish RPM and a nearly closed throttle, gradually open it, find the least open throttle position where acceleration stops increasing. Alternatively, starting from a fully open throttle and slowing closing it, find the most open throttle position where acceleration starts to decrease. The two methods should lead to the same throttle position, given identical conditions. Be reasonably quick with both methods as the engine state is changing all the time, which means that the throttle position threshold will move.) What is surprising is that the throttle position threshold occurs at low throttle openings up to quite high RPM. Consequently, at these RPM, very small changes in throttle position cause a large change in MAP and therefore significantly different ignition and fuel requirements by the engine. So a linearly mapped TPS-based look-up table has low resolution (i.e. provides coarse adjustments in ignition advance and fuel supplied to the engine) over a very important part of the RPM range. This can result in sub-optimal engine performance. Furthermore, the look-up table entries for medium-high TPS values at these RPMs are effectively wasted space, and, if mapped correctly, they should all contain the same values since the engine demands do not change over this range.
The above is demonstrated in the following plots, taken from data that I recorded on a single, normal (i.e. ordinary road) journey:
This plot and this plot indicate what proportion of time was spent at each TPS value - so it is clear that very little time is spent at throttle openings over 30%. This plot and this plot indicate what proportion of time was spent at each MAP value - which clearly shows a greater spread than a TPS. This plot indicates the relationship between TPS and MAP values when the inlet manifold pressure is near its maximum (i.e. the vacuum is near its minimum). The green line shows the minimum throttle opening that gives rise to maximum inlet manifold pressure, for each RPM. This throttle opening is the throttle position threshold. You can see that the throttle position threshold is 20% of maximum throttle opening at RPMs upto 4000!
This plot shows the areas of the map that are most commonly used. Note the peak around 800/1000RPM, when the engine is idling and the car is at rest. Apart from that, in normal road conditions, the 1600-3600 RPM band is where the engine spends most of its time, and therefore needs the most precise tuning.
The 'down' side to MAP sensors is that they can produce noisy measurements, particularly in highly tuned engines where high-overlap cams are used. However, hardware and software mechanisms exist which can smooth out this noise, and the noise is most significant at lower RPM.
Just in case you are worried that you might be stranded in the middle of nowhere if this system should let you down, the clever ignition module has a 'limp home' mode. Up to 2000RPM, the engine will receive the static advance that the distributor is set to. Above 2000RPM, the ignition module applies an extra 10 degrees of advance. This is surprisingly effective, and very driveable.
| Part | Cost me |
| (used) GM (not Vauxhall) ECM (waterproof) | £30 (but can be bought for less these days) |
| (new) Emerald (RS) TPS & bracket | £25 |
| (used) GM (not Vauxhall) ignition module (HEI) | £10 |
| (used) GM/Vauxhall MAP sensor | £10 |
| (used) GM/Vauxhall connectors | free |
| (new) Wire - to extend ECM wires | ~£10 |
| (used) Distributor (requires fitment of reluctor sensor from another distributor) - to provide speed input | ~£20 |
| Welding up of above distributor to prevent any mechanical advance | ~£5 |
| (new) 27C256 EPROM to program ECM (but I was lucky enough to find a few spares in a skip, at my work place) | ~£5 |
| (new) Waterproof dash connector to interface ECM to lap-top | spare from where I work, so - free |
| (used) Vauxhall CTS (arguably not absolutely essential for ignition alone) | came with my engine, so - free |
| Total | ~£115 |
| Item | Cost me |
| Very old lap-top PC (for connection to the GMECM via the diagnostic data stream) | thrown away from where I work, so - free |
| Diagnostic data stream (ALDL) RS232C interface circuit (to change from TTL to RS232C standard voltage levels) | reject board from where I work, modified by me, so - free |
| ALDLMON - Diagnostic data stream (ALDL) monitoring & recording software (MSDOS). This is written to work with $8D ECM software variant of the data stream, but is available with (Pascal) source code, so that you can make corrections/changes. (I no longer use it as have written my own version for the Sunbird code, in 'C'.) | freeware - including source code |
| WinBin - MS Windows based $8D EPROM configuration software. (I no longer use it.) | freeware |
| Lots of small, data interfacing/manipulation/analysis programs (MSDOS) | written by me, so - free |
| EPROM programmer, supporting 27C256 | thrown away from where I work, so - free |
| EPROM (UV) eraser | thrown away from where I work, so - free |
| Strobe light (for viewing ignition advance at the crank pulley) | I had one of these anyway, so - free |
| Oscilloscope (for viewing ignition and injector firing pulses) | thrown away from where I work, so - free |
| Registered copy of PROMgrammer (for ease of modifying $58 calibration data) | $10 |
| Total | $10 |
Having painted what might seem like a 'rosey' picture at this point (or maybe not?), I must point out the problems with use of GMECMs:
(*) However, GMECM software can be changed to read any of its calibration data (including look up tables etc.) from RAM instead of ROM (provided you have GMECM hardware which has RAM - like mine does). To exploit this, I modified my ECM software to accept commands (va ALDL) to change values in RAM, and wrote PC software to provide a user-friendly means of changing RAM values on-the-fly, in the style of COTS packages. This setup is currently configured for the main ignition advance and VE tables - as these need to be iteratively modified to exactly suit the engine. The best place to do this is on a rolling road - where the values can be optimised for maximum engine power and mapping is made easier by being able to hold engine load and speed constant (to get enough data to optimise a given cell of the look up table). However, road tests, in conjunction with a wide-band lambda based real-time mixture sensing system, can achieve similar performance, but takes longer. My PC software allows the improved table values to be saved to disk - which can then be transferred to EPROM for long term use.
So, you can see that using GMECMs is not for the technophobe, but within easier reach than when I started. To get to this point I have had to go through a steep learning curve, which has taken years and hundreds of hours, much to the disgust of my wife... But I've loved it!
| Part | Cost me |
| (new) Thermistor that matches the GM MAT (and CTS) resistance curve - to use as a MAT sensor | £1.38 |
| Part | Cost me |
| (used) Vauxhall Cavalier 2.0 16v injector rail, injectors, and regulator | came with engine, so - free |
| Welding of chopped SBD DCOE manifold to chopped standard 20XE injection manifold | £30 |
| (used) VW EFi 'swirl pot' | £10 |
| (used) 2 x DCOE 40 to convert to TBs | £55 (minus £55 that I got for the jets and stuff) = £0 net |
| (new) VW (Bosch) EFi fuel pump - fits inside swirl pot | £135 |
| (new) EFi fuel filter - fits to swirl pot | £7.36 |
Thanks to Bill Shurvinton for the idea, acting as an agent for the provision of the american GM hardware, and his early suggestions about the ANHT/$8D software.
Thanks to Ward Spoonemore AKA ECMGuy (RIP) for his substantially commented hack of the 1227727 Corvette ECM software.
Thanks to Steve Ravet for the GMECM e-mail list.
Thanks to Shawn R. Lin at the W-Body page for the ECM and MEMCAL pictures.
Thanks to Eric Aos for Winbin (which I used to use when I was working with ANHT). As of 29Jun14, it is available for download from here.
Thanks to Carsten Meyer for ALDLMON and his ALDL interface circuit diagram (neither of which appear to be on-line any more). Peter Gargano's circuit diagram used to be found here but sadly no longer. I have since written my own version of ALDLMON from scratch.
Thanks to Donna Whisnant for her code-seeking 68HC11 disassembler, now called GenDasm (generic disassembler).
Thanks to Orgler Electronic for their 68HC11 assembler. This no longer appears to be on-line, but there are plenty out there which can be found by Googling.
Thanks to Bill Calcagno for PROMgrammer (an excellent tool for Sunbird/$58 tuning). I have a registered copy. Sadly a dead link now.
Thanks to Wabasoft for Waba. Sadly a dead link now.
Thanks to other GMECM gurus e.g. Bruce Plecan (RIP), Robert Rauscher, Peter Gargano, Shannen Durphey, Ludis Langens, and others...
Thanks to my colleague, Geoff Hatto, for his PC-based 'C' serial data and cursor positioning software.
I accept no responsibility for the accuracy or inaccuracy of any of the information on these web pages, nor any problems/damage resulting from the use of it.