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.
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 |
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.
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).
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.
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.
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.
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:
|
|
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.
A communication channel to the ECM is established by setting up a serial link using these settings:
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 # | Meaning | Values (typical) | Remarks |
---|---|---|---|
1 | SOH | 0x01 | Start of Header |
2 | Emittend | 0x00 | From PC |
3 | Recipient | 0x42 | To ECM |
4 | Data Size | 0x05 | Number of Bytes from SOT incl. EOT |
5 | EOH | 0xFF | End of Header |
6 | SOT | 0x02 | Start of Text |
7 | Data 1 |
|
Command |
8 | Data 2 | 0x00 | Page Offset |
9 | Data 3 | 0x01 | Page No. |
10 | Data 4 | 0x01 | EEPROM Data |
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 # | Meaning | Values (typical) | Remarks |
---|---|---|---|
1 | SOH | 0x01 | Start of Header |
2 | Emittend | 0x42 | From ECM |
3 | Recipient | 0x00 | To PC |
4 | Data Size | 0x03 | Number of Bytes from SOT incl. EOT |
5 | EOH | 0xFF | End of Header |
6 | SOT | 0x02 | Start of Text |
7 | Data 1 (ACK/NAK) |
|
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 | 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 | 0x57 | Command |
8 | Data 2 | 0x00 | Page Offset |
9 | Data 3 | 0x20 | Virtual Page No. |
10 | Data 4 |
|
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 # | Meaning | Values (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 |
|
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.