The EEPROM is a non-volatile storage for a small amount of data. The EEPROM is built into the ECM and holds about 1 kbyte of configuration data (DDFI-2), which could be read from and written into the storage. From 2004 on XB9 as well as XB12 models share the same ECM hardware, but with different data in them. The ECMs used for XB12 models have to support the exhaust valve and either the maps, timing tables and rev limiter look different. The EEPROM content is made up of more than 200 different scalars and tables, many of those could be identified. The following chapter shows a list of values together with their offsets, scaling and translation factors, the units and a short description.

Note: all data given is for ECM models before 2008 (DDFI-2). The new ECMs used in the 2008 and later models (DDFI-3) have a different EEPROM size and a very different EEPROM layout.


The EEPROM layout describes the position and size of every (known to us) value contained in the EEPROM data. Without knowing this information, the EEPROM is just a large area filled with binary data, but knowing about the position a variable opens the way to adjust it's value with a offline editor like WinOLS or TunerPro (see the tools page for more information about these applications). The EERPOM layout is described in detail in the various chapters in this section, but to use the abovementioned programs a file is required which describes the EERPOM layout in a machine-readable form. Those who prefer using the TunerPro application can download the EEPROM definitions directly from the ECM info pages. These are written for version 4 of TunerPro, available on the TunerPro download page.

How to access the EERPOM?

The EEPROM holding configuration data has a size of about 1 kbyte (DDFI and DDFI-2), but one byte can only hold a value up to 255 - so offsets above this would never be accessable. Therefore the EEPROM is divided into pages, this is a common procedure. The ECM's EEPROM is divided into 5 or 6 pages, depending on the ECM type - the tubeframer's ECMs are only 5 pages large. Each page consists of up to 256 bytes, with an offset from 0 (first byte) to 255 (last byte). Pages 1, 2, 4 and 5 are usually 256 bytes large, the pages 3 and 6 (if available) are of variable length. Page 3 always ends with the fuel map's and timing table's X and Y axis, and page 4 always starts with the timing tables, followed by the fuel maps.
So to access the EEPROM you have to calculate the page and the page-offset of the byte you want to access. The following tables shows the various pages sizes for different ECM types:

ECM Type Pagesize (bytes)
Page 1 Page 2 Page 3 Page 4 Page 5 Page 6
CB050 256 256 90 256 256 24
CB060 256 256 90 256 256 24
GB231 256 256 150 256 256 24
IB310 256 256 158 256 256 24

How to read those numbers?

The offsets are given in hexadecimal notation, which is based on the number 16 instead of the usual decimal system, based on the number 10. Hexadecimal numbers are built from the numerals 0-9 (representing 0-9 in decimal) and the characters a-f representing 10-15 in decimal.
A single page in the EEPROM can hold up to 256 values, which could be thought of as a quadratic range of 16 rows ∗ 16 columns:

0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f
0x00 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f
0x10 0x10 0x11 0x12 0x13 0x14 0x15 0x16 0x17 0x18 0x19 0x1a 0x1b 0x1c 0x1d 0x1e 0x1f
0x20 0x20 0x21 0x22 0x23 0x24 0x25 0x26 0x27 0x28 0x29 0x2a 0x2b 0x2c 0x2d 0x2e 0x2f
0x30 0x30 0x31 0x32 0x33 0x34 0x35 0x36 0x37 0x38 0x39 0x3a 0x3b 0x3c 0x3d 0x3e 0x3f
0x40 0x40 0x41 0x42 0x43 0x44 0x45 0x46 0x47 0x48 0x49 0x4a 0x4b 0x4c 0x4d 0x4e 0x4f
0x50 0x50 0x51 0x52 0x53 0x54 0x55 0x56 0x57 0x58 0x59 0x5a 0x5b 0x5c 0x5d 0x5e 0x5f
0x60 0x60 0x61 0x62 0x63 0x64 0x65 0x66 0x67 0x68 0x69 0x6a 0x6b 0x6c 0x6d 0x6e 0x6f
0x70 0x70 0x71 0x72 0x73 0x74 0x75 0x76 0x77 0x78 0x79 0x7a 0x7b 0x7c 0x7d 0x7e 0x7f
0x80 0x80 0x81 0x82 0x83 0x84 0x85 0x86 0x87 0x88 0x89 0x8a 0x8b 0x8c 0x8d 0x8e 0x8f
0x90 0x90 0x91 0x92 0x93 0x94 0x95 0x96 0x97 0x98 0x99 0x9a 0x9b 0x9c 0x9d 0x9e 0x9f
0xa0 0xa0 0xa1 0xa2 0xa3 0xa4 0xa5 0xa6 0xa7 0xa8 0xa9 0xaa 0xab 0xac 0xad 0xae 0xaf
0xb0 0xb0 0xb1 0xb2 0xb3 0xb4 0xb5 0xb6 0xb7 0xb8 0xb9 0xba 0xbb 0xbc 0xbd 0xbe 0xbf
0xc0 0xc0 0xc1 0xc2 0xc3 0xc4 0xc5 0xc6 0xc7 0xc8 0xc9 0xca 0xcb 0xcc 0xcd 0xce 0xcf
0xd0 0xd0 0xd1 0xd2 0xd3 0xd4 0xd5 0xd6 0xd7 0xd8 0xd9 0xda 0xdb 0xdc 0xdd 0xde 0xdf
0xe0 0xe0 0xe1 0xe2 0xe3 0xe4 0xe5 0xe6 0xe7 0xe8 0xe9 0xea 0xeb 0xec 0xed 0xee 0xef
0xf0 0xf0 0xf1 0xf2 0xf3 0xf4 0xf5 0xf6 0xf7 0xf8 0xf9 0xfa 0xfb 0xfc 0xfd 0xfe 0xff

The table shows the rows and columns in bold and the associated offset in normal font. The offset is made from the row's number as first and then the column's number added to it as second cipher. It gets prefixed with "0x" to denote the hexadecimal base. A third and fourth cipher in the offset value could be thought of a page number. Unfortunately, as said before, this doesn't work with the EEPROM here because of the variable page size and the first page starting with number 1 instead of 0.

As an aid in calculation of page and page-offset from the linear offset given in the EEPROM directory, please use the following table:

Page 1 Page 2 Page 3 Page 4 Page 5 Page 6
ECM Type from to from to from to from to from to from to
CB050 0x0000 0x00ff 0x0100 0x01ff 0x0200 0x0259 0x025a 0x0359 0x035a 0x0459 0x045a 0x0471
CB060 0x0000 0x00ff 0x0100 0x01ff 0x0200 0x0259 0x025a 0x0359 0x035a 0x0459 0x045a 0x0471
GB231 0x0000 0x00ff 0x0100 0x01ff 0x0200 0x0295 0x0296 0x0395 0x0396 0x0495 0x0496 0x04ad
IB310 0x0000 0x00ff 0x0100 0x01ff 0x0200 0x029d 0x029e 0x039d 0x039e 0x049d 0x049e 0x04b5

The more recent EEPROM layouts for DDFI-3 ECM types are much larger (about triple size), but fortunately simpler also. All pages, except the last one, are of the same size (256 bytes), so addressing is getting much easier.

Variable types used in the EEPROM storage

Differen types of data are stored accross the EEPROM address space. Looking at the EEPROM directory you will notice types of bitfields (bits), numeric values (value), ordered and unordered arrays of values (list) and values, that could be shown best in a tabular form (tables).

Type "Value"

A variable of type "value" holds a single number. Dependent on the size of this number it is stored in one byte (range 0-255) or in two bytes (range 0-65535). Numbers stored in two bytes get the lower byte stored at the lower and the higer byte stored at the higher EEPROM offset. The decimal number 5000 for example is written 0x1388 in hexadecimal and will be stored in two bytes: 0x88 followed by 0x13.

Type "Bits"

A bitfield is special value. Here every of the eight bits has as special meaning, which has nothing to do with it's numeric value. Bits will be switched on (holding a value of 1) or switched off (holding a value of 0). Bitfields are usually used to hold error codes or configuration settings and could be thought of a list of features, where each can be enabled or disabled by setting the appropriate bit to 0 or 1 respectively. A bitfield holding the numeric value of 177 (in decimal) would be written 10110001 in binary (with the most significant bit at the leftmost position), such enabling the features bound to the bits 0.4,5 and 7.

Type "Array", "Axis"

An array is a sequence or list of values, sometimes ordered, sometimes unordered. Axises are a special type of array, used as the representation of an x- or y-axis in conjunction with maps or tables (see below). The values building up a list can be one or two bytes of size, dependent on the largest numeric value they will have to hold.

Type "Table", "Map"

Tables and maps are large collections of numbers that require one (tables) or two (maps) axises to look up the wanted value. Three-dimensonal tables, linked to x- and y-axises , are called maps.
The majority of the two dimensional tables are stored as a large list with alternating values and are self-contained, this means, the lists contain not only the table data, but also the axis. As an example, the air density correction, which is dependent on air temperature and used to look up the required correction factor, will be read from the EEPROM as this sequence of decimal numbers: 0. 125, 40. 110. 65, 100. 90. 90. 115, 82, 140. 74, 165, 68. This array builds a 2-column, 7-row table where the left column represents the air temperature (even list positions, this is the axis value) and the right column the correction factor (odd list positions, this is the data value). The temperature list furthermore needs to be translated correctly. The axis is the input, the data the output value. To get the correction applied at e. g. 90 °C, you look for the nearest lower value (75) and next higher value (100), where 90 is 15/25 of the full difference. Then the same ratio gets applied to the difference of the two correction values: 82 + 15/25 * (74-82) = 77.2. This is the interpolated result. The raw and the translated numbers are shown in the two tables following:

Air Density Corr.
Temp. (raw) Corr.
0 125
40 110
65 100
90 90
115 82
140 74
165 68
Air Density Corr.
-40 125
0 110
25 100
50 90
75 82
100 74
125 68

All self-contained tables consist of values of the same size, one or two bytes large, unlike maps, where axis and cell values could be of different types, such as the fuel maps or the timing table, where the x-axis (RPM axis) is made of 2-byte numbers.

How to communicate with the ECM

A communication channel to the ECM is established by setting up a serial link using these settings:

  • 9600 bits per second
  • 8 databits
  • 1 stopbit
  • no parity
  • no flow control
  • TTL voltage levels (logical 0 < 0.8 volts, logical 1 > 2.0 volts). Voltage must not exceed 5.0 volts!

The communication protocol consits of an exchange of data records. The computer application is sending requests, which in turn are responded to by the ECM. Each data record consists of a header, then followed by payload and is terminated by a checksum. The header describes the emmittend and the recipient as well as the payload length. A request's payload contains a command, followed by data if necessary.

A typical request for EEPROM data is described in the following table:

Byte #MeaningValues (typical)Remarks
1 SOH 0x01 Start of Header
2 Emittend 0x00 From PC
3 Recipient 0x42 To ECM
4 Data Size 0x05 5 Bytes
5 EOH 0xFF End of Header
6 SOT 0x02 Start of Text
7 Data 1
  • 0x52 = Get
  • 0x57 = Set
8 Data 2 0x00 Page Offset
9 Data 3 0x01 Page No.
10 Data 4 0x01 Number of Bytes
11 Data 5 (EOT) 0x03 End of Text
12 Checksum 0xEB XORed Checksum

In case of a response the payload starts with a code, also followed by data if required. The code describes wether the request was successfull or not, and payload contains just a more specific error code then. The ECM's response would then look like shown in the table below, showing the value of 0 at page number 1 and offset 0. In case of a write request (code 0x57) no data will be returned, so the data size is always 2 bytes (0x06 0x03) then, in case no error is returned.

Byte #MeaningValues (typical)Remarks
1 SOH 0x01 Start of Header
2 Emittend 0x42 From ECM
3 Recipient 0x00 To PC
4 Data Size 0x03 3 Bytes
5 EOH 0xFF End of Header
6 SOT 0x02 Start of Text
7 Data 1 (ACK)
  • 0x06 = Success
  • else = Error
Error Indicator
8 Data 2 0x00 EEPROM Data
9 Data 3 (EOT) 0x03 End of Text
10 Checksum 0xE0 XORed Checksum

In addition to those pages, that are physically present in the EEPROM, the ECM firmware supports a virtual page 32 (0x20 in hexadecimal). Writing values to the page offset 0 of this page trigger pre-defined functions, such as a TPS reset or running various tests. The example below shows a "Clear DTC" command. Just as with the EEPROM write commands, the ECM responds with a single ACK response, containing no data.

Byte #Meaning Values (typical)Remarks
1 SOH 0x01 Start of Header
2 Emittend 0x00 From PC
3 Recipient0x42 To ECM
4 Data Size0x05 5 Bytes
5 EOH 0xFF End of Header
6 SOT 0x02 Start of Text
7 Data 1 0x57 Command
8 Data 2 0x00 Page Offset
9 Data 3 0x20 Virtual Page No.
10 Data 4
  • 0x01 = Clear Codes
  • 0x02 = Front Coil
  • 0x03 = Rear Coil
  • 0x04 = Tachometer
  • 0x05 = Fuel Pump
  • 0x06 = Front Inj.
  • 0x07 = Rear Inj.
  • 0x08 = TPS Reset
  • 0x09 = Fan
  • 0x0a = Exh. Valve
Data Byte
(Device Selector or Reset Code)
11 Data 5 (EOT)0x03 End of Text
12 Checksum 0xCF XORed Checksum

Reading one byte from virtual page 32, offset 0 returns the current ECM status. A value of 0x00 signals normal operation, any other value indicates a busy state.

The command set includes two one-byte commands, that are used to retrieve the ECM firmware version and a set of runtime data from the ECM:

Byte #MeaningValues (typical)Remarks
1 SOH 0x01 Start of Header
2 Emittend 0x00 From PC
3 Recipient 0x42 To ECM
4 Data Size 0x02 2 Bytes
5 EOH 0xFF End of Header
6 SOT 0x02 Start of Text
7 Data 1
  • 0x56 = Get Version
  • 0x43 = Get Runtime Data
Command Code
8 Data 2 (EOT) 0x03 End of Text
9 Checksum 0xE8 XORed Checksum

An easy way to discover the various functions available might be to take a look at the sources for the PalmOS application, available here. The source is NOT in the public domain, but published under the GPL V2, so all restrictions from this licence apply. Any commercial use of the sources provided is strictly prohibited. If in doubt, contact the developers, please.