Page 2 of 2
Re: Read and write mileage from IPC (EEPROM)
Posted: 13 Jul 2019, 15:38
by Ursadon
Go4IT wrote: ↑13 Jul 2019, 15:17
Yes, you're right. Even the algo you formed is more compact than mine, but it is exactly the same. Reverse engineered from IPC firmware.
There is another one at 0x778 as 4 bytes. Coded with parity and CRC, multiplied by 10, giving two numbers behind comma. This seems the one shown in the TEST modus of the IPC. I only miss the one for the trip odo. It must be there also. Just for completeness
BTW: Did you manage to write the EEPROM via CAN now?
Thx for 0x778, i forgot about this value
I have a proof-of-concept eeprom write algo.
Since i2c mapped to 0x6000000, it easy to write to it using Secondary Bootloader (*-AA.vbf). I think, UCDS using same technique to correct odometer value.
Re: Read and write mileage from IPC (EEPROM)
Posted: 13 Jul 2019, 17:53
by Go4IT
Ups, sorry, typo, i mean 0x788 not 0x778 !
Re: Read and write mileage from IPC (EEPROM)
Posted: 13 Jul 2019, 19:48
by Go4IT
At least it is very simple to calc the ODO from the bytes. Just take the two first bytes at offset 0x774 as a word, shift this by 4 bits to right (=divide by 0x10) and multiply it by 5 and 0x80 and store this value. Then take the last byte of each of the 4-byte groups, logical and it with 0x7F and add 0x01 to the value. Add all those values to the previous stored value. Then divide that by 5 and add 1 and you got your KM value.
Example: 0x774
79 D9 FF 26 79 D9 FF A2 79 D9 FF 23 79 D9 FF A4 79 D9 FF 25
Code: Select all
KM_HIGH = (0x79D9 / 0x10) * 5 * 0x80 = 0x13 0880
KM_LOW = 0x27 + 0x23 + 0x24 + 0x25 + 0x26 = 0xB9
KM = (0x130880 + 0xB9) / 5 + 1 = 0x3CEA6 (=249.510km)
Re: Read and write mileage from IPC (EEPROM)
Posted: 14 Jul 2019, 02:44
by Ursadon
Go4IT wrote: ↑13 Jul 2019, 19:48
At least it is very simple to calc the ODO from the bytes. Just take the two first bytes at offset 0x774 as a word, shift this by 4 bits to right (=divide by 0x10) and multiply it by 5 and 0x80 and store this value. Then take the last byte of each of the 4-byte groups, logical and it with 0x7F and add 0x01 to the value. Add all those values to the previous stored value. Then divide that by 5 and add 1 and you got your KM value.
Example: 0x774
79 D9 FF 26 79 D9 FF A2 79 D9 FF 23 79 D9 FF A4 79 D9 FF 25
Code: Select all
KM_HIGH = (0x79D9 / 0x10) * 5 * 0x80 = 0x13 0880
KM_LOW = 0x27 + 0x23 + 0x24 + 0x25 + 0x26 = 0xB9
KM = (0x130880 + 0xB9) / 5 + 1 = 0x3CEA6 (=249.510km)
You forgot to prepend KM_HIGH with inverted high halfbyte of 79D9
FF26.
Otherwise the max km value is 524288+640
Re: Read and write mileage from IPC (EEPROM)
Posted: 14 Jul 2019, 08:19
by Go4IT
Here is a C example off how to decode mileage from bytes:
Code: Select all
BYTE g_ubMileage[20];
// CRC Table. 16 Bytes found in 1MB Flash ("7M2T-14C026-AG") at 0x4B064
BYTE g_ubCrc8Bit[16] =
{
0x0, 0xD, 0x7, 0xA,
0xE, 0x3, 0x9, 0x4,
0x1, 0xC, 0x6, 0xB,
0xF, 0x2, 0x8, 0x5,
};
// return word from mileage data entry (five entries, four bytes each) in Big Endian
WORD get_mileage_entry(int idx, int iWord)
{
if(idx < 0 || idx > 4)
return 0xFFFF;
if(iWord != 0 && iWord != 1)
return 0xFFFF;
return (g_ubMileage[(idx * 4) + (iWord * 2) + 0] << 8) |
(g_ubMileage[(idx * 4) + (iWord * 2) + 1] << 0);
}
// calculate 4-bit CRC of a 16-bit word
BYTE calc_crc_4bit(WORD w)
{
BYTE ubCrc = 0xF;
int i;
for(i = 0; i < 4; i++)
{
ubCrc = g_ubCrc8Bit[ubCrc] ^ (w & 0xF);
w = (w >> 4);
}
return ubCrc;
}
// get parity bit of a byte (even/odd)
BYTE get_parity(BYTE ub)
{
BYTE ubParity = 0;
while(ub != 0)
{
ubParity++;
ub &= (ub - ubParity);
}
return ubParity & 0x01;
}
// get MSB mileage bits, check for valid CRC
WORD get_mileage_entry_and_check_crc(int idx)
{
if(idx < 0 || idx > 4)
return 0xFFFF;
WORD w1 = get_mileage_entry(idx, 0);
WORD w2 = get_mileage_entry(idx, 1);
BYTE ub = (w2 >> 8); // MSB of word
WORD w = (w1 >> 4) | (((~ub) & 0xF0) << 8);
BYTE ubCrc = calc_crc_4bit(w);
if(ubCrc == (w1 & 0x0F)) // CRC valid ?
return w;
else
return 0xFFFF;
}
// get LSB mileage bits, check for valid parity
WORD get_mileage_entry_and_check_parity(int idx)
{
if(idx < 0 || idx > 4)
return 0xFFFF;
WORD w1 = get_mileage_entry(idx, 0);
WORD w2 = get_mileage_entry(idx, 1);
BYTE ub = (w2 & 0xFF); // LSB of word
if(get_parity(ub)) // odd parity ?
return (ub & 0x7F) + 1;
else
return 0;
}
void calc_mileage(BYTE *ubMileage)
{
// copy data into buffer
memcpy(g_ubMileage, ubMileage, sizeof(g_ubMileage));
// calculate sum of each all five entries
DWORD dw1sum = 0;
WORD w2sum = 0;
int i;
for(i = 0; i < 5; i++)
{
WORD w1 = get_mileage_entry_and_check_crc(i); // MSB of mileage
WORD w2 = get_mileage_entry_and_check_parity(i); // LSB of mileage
dw1sum += w1;
w2sum += w2;
}
// combine MSB and LSB
DWORD dw = (dw1sum << 7) + w2sum;
// final calulation, 200 meter resolution
dw = (dw / 5) + 1;
return(dw);
}
// try it...
void main()
{
// Test data of 249.510 km (offset 0x774)
BYTE testdata[20] =
{
0x79, 0xD9, 0xFF, 0x26,
0x79, 0xD9, 0xFF, 0xA2,
0x79, 0xD9, 0xFF, 0x23,
0x79, 0xD9, 0xFF, 0xA4,
0x79, 0xD9, 0xFF, 0x25,
};
WORD km = calc_mileage(testdata);
printf("Mileage is %d km\n", km);
}
Re: Read and write mileage from IPC (EEPROM)
Posted: 14 Jul 2019, 08:26
by Go4IT
Ursadon wrote: ↑14 Jul 2019, 02:44
You forgot to prepend KM_HIGH with inverted high halfbyte of 79D9
FF26.
Otherwise the max km value is 524288+640
Yes, it was a known simplyfication, just to demonstrate how the algo works
The beauty of this design is that EEPROM data changes for the lower bits of the milage are distributed over 5 memory locations in turn. So by writing the milage every 200 meter will result in a theoretical max. of 1 million kilometers.
Re: Read and write mileage from IPC (EEPROM)
Posted: 14 Jul 2019, 09:15
by Go4IT
I try to figure out how to do the reverse, calc bytes from odo (Pseudo-Code):
Code: Select all
function calc_crc(DWORD) {
...
}
DWORD km = 0x3CEA6; // =249.510 km
DWORD dw = (km - 1) * 5 // =0x130939
DWORD dw1sum = dw / 0x80 // =0x2612 (equals dw >> 7)
WORD w2sum = (dw - dw1sum) & 0x7F // =0x28
WORD dw1crc = calc_crc(dw1sum)
WORD msb = (dw1crc * 0x100) | dw1sum
WORD lsb[5] = ...
Re: Read and write mileage from IPC (EEPROM)
Posted: 22 Sep 2019, 09:43
by Gwe89
Hi does your new tool only work with the els27
Re: Read and write mileage from IPC (EEPROM)
Posted: 22 Sep 2019, 09:56
by Artist
Yes, the official release only supports Els 27.
You need to buy it, it's not a bad investment ...
Re: Read and write mileage from IPC (EEPROM)
Posted: 29 Sep 2019, 19:27
by Gwe89
I have been changing mileage this way years ago I found where to edit by reading the eeprom and then setting mileage to 0 with ucds then reading it again then compared them both
AF 00 00 FF EF 00 06 FF 80 00 06 FF 80 00 06 FF 80 00 06 FF 80 00 06 FF 80 D0 00 00 32
sets it to 0