Mitsubishi FTO Speedometer
Speedometer-Odometer from Mitsubishi FTO
- https://carrott.org/blog/archives/154-Speedometer.html
- https://carrott.org/git/eeprom_sniffer.git
- https://carrott.org/git/speedo_test.git
- 2548 pulses per km
Odometer Value
The odometer value is stored in an 8 pin serial EEPROM with markings OKI 16811g 4411. OKISD005-747.pdf describes how this part works. This EEPROM uses Microwire which is a subset of SPI. I wrote my own code to bit-bang the protocol with an Arduino in EEPROM Sniffer.
The raw data stored by the odometer is a bit strange, the eeprom is organized in 16 bit words and indexed with binary coded decimal, which means words with the bit 7 set (ie 0xA through 0xF) are skipped. In thie following example, these words are all zeros. The odometer stores it's data with all the bits flipped, the following sample has reversed this so we can read the binary coded decimal.
00000000: 42 10 42 10 42 10 42 10 42 10 42 10 42 10 42 10 B.B.B.B.B.B.B.B. 00000010: 42 10 42 10 00 00 00 00 00 00 00 00 00 00 00 00 B.B............. 00000020: 42 10 21 08 21 08 21 08 21 08 21 08 21 08 21 08 B.!.!.!.!.!.!.!. 00000030: 21 08 21 08 00 00 00 00 00 00 00 00 00 00 00 00 !.!............. 00000040: 42 10 42 10 67 39 04 21 42 10 42 10 42 10 42 10 B.B.g9.!B.B.B.B. 00000050: 42 10 42 10 00 00 00 00 00 00 00 00 00 00 00 00 B.B............. 00000060: 21 08 04 21 2D 6B 42 10 67 39 7F FF 4E 73 7F FF !..!-kB.g9..Ns.. 00000070: 7F FF 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
The data itself starts to make more sense when we eliminate the skipped addresses, group into 16 bit words and count them in base 10:
00000000: 4210 4210 4210 4210 4210 4210 4210 4210 4210 4210 00000010: 4210 2108 2108 2108 2108 2108 2108 2108 2108 2108 00000020: 4210 4210 6739 0421 4210 4210 4210 4210 4210 4210 00000030: 2108 0421 2D6B 4210 6739 7FFF 4E73 7FFF 7FFF 0000
The above data encodes a km value of 190090. The low nibble of each word is binary coded decimal admd the remaining nibbles are some sort of check pattern. If you write incorrect values in the high nibbles then the odometer displays an error.
In this example, words 0-19 encode 90 in a wear levelling arangement. The same value is written into each of the 20 addresses and when all 20 have been written, it starts again with a different word. The position where the word changes from the old to the new one indicates 0 through 20. 5 different words are used to indicate 0, 20, 40, 60 and 80. This way the write load on the memory is divided by 20. Set the first word to 0x0421 and the rest to 0x4210 to zero the two least significant digits. In the example above, 2108 means 80 and is being overwritten by 4210. The most recent 4210 was written at address 10, so we add 10 to 80 and get 90.
In this example, words 20-23 encode 1900 (ie the next 4 most signficant digits), reading right to left. The alphabet for these words is:
0x4210 | 0 |
0x0421 | 1 |
0x0842 | 2 |
0x4e73 | 3 |
0x1084 | 4 |
0x56b5 | 5 |
0x5ad6 | 6 |
0x1ce7 | 7 |
0x2108 | 8 |
0x6739 | 9 |
Adding the two parts together we get 190090 which is displayed on the odometer.
Needle Calibration
The mini face spreads the 180km/h over a wider range.
I didn't find a way to change the number fo pulses per km, but I did find a calibration for the needle at addresses 31 and 32 (in the base 10 table above).
- Changing 32 from 0x2D6B to 0xFFF9 makes the needle go further
- Changing 31 from 1 to 2 appears to move the zero point
- The only valid values of 30 appear to be 8 and 9. All other values from the alphabet above cause the needle not to move and odometer not to count. With this address set to 9, the needle doesn't go as far for any particular speed. It seems likely 8 is for 180km/h speedo and 9 is for 240km/h.
- Address 31
Value | Speed at 50 | Speed at 100 | Speed at 180 |
0 | 45 | 80 | 140 |
1 | 53 | 95 | 170 |
2 | 60 | 110 | >> |
3 | 70 | 127 | >> |
4 | 45 | 80 | 140 |
5 | 53 | 95 | 170 |
6 | 60 | 110 | >> |
7 | 70 | 127 | >> |
8 | 45 | 80 | 140 |
9 | 53 | 95 | 170 |
- Addresses above 33 don't appear to do anything