EnableExplicit Enumeration #OK = 0 #ERROR = -1 EndEnumeration DataSection Crc8Bit: ; calculate 4-bit CRC Data.a $00, $0D, $07, $0A, $0E, $03, $09, $04 Data.a $01, $0C, $06, $0B, $0F, $02, $08, $05 ; g_ubMileage_249503: ; Data.a $79, $D9, $FF, $1C, $79, $D9, $FF, $9D, $79, $D9 ; Data.a $FF, $9E, $79, $D9, $FF, $1F, $79, $D9, $FF, $9B ; g_ubMileage_249504: ; Data.a $79, $D9, $FF, $1C, $79, $D9, $FF, $9D, $79, $D9 ; Data.a $FF, $9E, $79, $D9, $FF, $1F, $79, $D9, $FF, $20 ; g_ubMileage_249505: ; Data.a $79, $D9, $FF, $A1, $79, $D9, $FF, $9D, $79, $D9 ; Data.a $FF, $9E, $79, $D9, $FF, $1F, $79, $D9, $FF, $20 ; g_ubMileage_249510: ; Data.a $79, $D9, $FF, $26, $79, $D9, $FF, $A2, $79, $D9 ; some test Data at EEPROM offset 0x774 ; Data.a $FF, $23, $79, $D9, $FF, $A4, $79, $D9, $FF, $25 ; 249510 km ; g_ubMileage_249516: ; Data.a $79, $D9, $FF, $AB, $79, $D9, $FF, $2C, $79, $D9 ; some test Data at EEPROM offset 0x774 ; Data.a $FF, $A8, $79, $D9, $FF, $29, $79, $D9, $FF, $2A ; 249516 km ; g_ubMileage_249648: ; Data.a $79, $E0, $FF, $AD, $79, $E0, $FF, $AE, $79, $E0 ; some test Data at EEPROM offset 0x774 ; Data.a $FF, $2F, $79, $E0, $FF, $B0, $79, $E0, $FF, $2C ; 249648 km ; g_ubMileage_2: ; 0, 0, 0, 0, 0 = 0 / 5 = 0 + 2 = 2 ; Data.a $00, $06, $FF, $80, $00, $06, $FF, $80, $00, $06 ; Data.a $FF, $80, $00, $06, $FF, $80, $00, $06, $FF, $80 ; g_ubMileage_4: ; 0, 1, 2, 3, 4 = 10 / 5 = 2 + 2 = 4 ; Data.a $00, $06, $FF, $80, $00, $06, $FF, $01, $00, $06 ; Data.a $FF, $02, $00, $06, $FF, $83, $00, $06, $FF, $04 ; g_ubMileage_5: ; 1, 2, 3, 4, 5 = 15 / 5 = 3 + 2 = 5 ; Data.a $00, $06, $FF, $01, $00, $06, $FF, $02, $00, $06 ; Data.a $FF, $83, $00, $06, $FF, $04, $00, $06, $FF, $85 ; g_ubMileage_6: ; 2, 3, 4, 5, 6 = 20 / 5 = 4 + 2 = 6 ; Data.a $00, $06, $FF, $02, $00, $06, $FF, $83, $00, $06 ; Data.a $FF, $04, $00, $06, $FF, $85, $00, $06, $FF, $86 EndDataSection Procedure.a calc_crc_4bit_16(w.u) Protected i.b, ubCrc.a = $0F For i = 0 To 3 ubCrc = PeekA(?Crc8Bit + ubCrc) ! (w & $0F) w = (w >> 4) Next i ProcedureReturn ubCrc EndProcedure Procedure.a calc_crc_4bit_28(w.l) Protected i.b, ubCrc.a = $0F For i = 0 To 6 ubCrc = PeekA(?Crc8Bit + ubCrc) ! (w & $0F) w = (w >> 4) Next i ProcedureReturn ubCrc EndProcedure Procedure.i get_mileage_entry(idx.a, iWord.a, *u_mileage_entry, Array g_ubMileage.a(1)) ; get word from mileage Data entry (five entries, four bytes each) Protected retwert.u If idx < 0 Or idx > 4 ; 0, 1, 2, 3, 4 : Es gibt 5 Einträge a 4 Byte ProcedureReturn #ERROR EndIf If iWord <> 0 And iWord <> 1 ; erste oder zweite word ProcedureReturn #ERROR EndIf retwert = (g_ubMileage((idx * 4) + (iWord * 2)) << 8) retwert | (g_ubMileage((idx * 4) + (iWord * 2) + 1)) ; Big Endian PokeU(*u_mileage_entry, retwert) ProcedureReturn #OK EndProcedure ; Procedure.a get_parity(ub.a) ; get parity bit of a byte (even/odd) ; Protected ubParity.a = 0 ; Debug Bin(ub) ; While ub <> 0 ; ubParity + 1 ; Debug ubParity ; ub = ub & (ub - ubParity) ; Debug Bin(ub) ; Wend ; ProcedureReturn ubParity & $01 ; EndProcedure Procedure.a get_parity(ub.a) ; get parity bit of a byte (even/odd) Protected i.a = $80, p.a = 0 While i If ub & i p + 1 EndIf i >> 1 Wend ProcedureReturn p & $01 ; Anzahl High Bits ungerade 1, 3, 5, 7 EndProcedure Procedure.i get_mileage_entry_and_check_crc(idx.a, *u_mileage_entry, Array g_ubMileage.a(1)) ; get MSB mileage bits, check For valid CRC Protected w1.u, w2.u, ub.a, w.u, ubCrc.a, status.i If idx < 0 Or idx > 4 ProcedureReturn #ERROR EndIf status = get_mileage_entry(idx, 0, @w1, g_ubMileage()) ; word 1 If status = #ERROR ProcedureReturn #ERROR EndIf status = get_mileage_entry(idx, 1, @w2, g_ubMileage()) ; word 2 If status = #ERROR ProcedureReturn #ERROR EndIf ub = (w2 >> 8) ; MSB of word obere Byte von Word 2 w = (w1 >> 4) | (((~ub) & $F0) << 8) PokeU(*u_mileage_entry, w) ubCrc = calc_crc_4bit_16(w) If ubCrc = (w1 & $0F) ; CRC valid ? CRC in den unteren 4 bit des ersten word ProcedureReturn #OK Else ProcedureReturn #ERROR EndIf EndProcedure Procedure.i get_mileage_entry_and_check_parity(idx.a, *a_mileage_entry,Array g_ubMileage.a(1)) ; get LSB mileage bits, check For valid parity Protected w1.u, w2.u, ub.a, status.i If idx < 0 Or idx > 4 ProcedureReturn $FFFF EndIf status = get_mileage_entry(idx, 1, @w2, g_ubMileage()) If status = #ERROR ProcedureReturn #ERROR EndIf ub = (w2 & $FF) ; LSB of word If get_parity(ub) ; odd parity ? PokeA(*a_mileage_entry, (ub & $7F + 1)) ; Parity in unteren byte von word 2 ProcedureReturn #OK Else ProcedureReturn #ERROR EndIf EndProcedure Procedure.l calc_mileage(*ubMileage) Protected w1sum.l = 0, w2sum.l = 0, i.b = 0, w1.u, w2.a, status.i Protected Dim g_ubMileage.a(19) ; 20 Byte Buffer CopyMemory(*ubMileage, @g_ubMileage(0), 20) ; copy Data into buffer For i = 0 To 4 ; calculate sum of each all five entries status = get_mileage_entry_and_check_crc(i, @w1, g_ubMileage()) ; MSB of mileage If status = #ERROR Break EndIf w1sum + w1 status = get_mileage_entry_and_check_parity(i, @w2, g_ubMileage()) ; LSB of mileage If status = #ERROR Break EndIf w2sum + w2 Next i If status = #OK ProcedureReturn ((w1sum << 7) + w2sum) / 5 + 1 ; combine MSB And LSB Else ProcedureReturn #ERROR EndIf EndProcedure Procedure.s Show_mileage_1(*ubMileage) Protected mileage.l, a.i, Text.s mileage = calc_mileage(*ubMileage) Text = #Null$ For a = 0 To 19 : Text + RSet(Hex(PeekA(*ubMileage)), 2, "0") + " " : *ubMileage + 1 : Next a If mileage = #ERROR ProcedureReturn Text + "--> Crc And/Or Parity Error" Else ProcedureReturn Text + "--> " + Str(mileage) + " km --> CRC/Parity OK" EndIf EndProcedure Procedure.l calc_mileage_2(*mem) Protected wert.l = 0, a.l, crc.a For a = 0 To 3 wert + PeekA(*mem) If a < 3 wert << 8 EndIf *mem + 1 Next a crc = (wert >> 28) & $F wert & $0FFFFFFF If crc = calc_crc_4bit_28(wert) ProcedureReturn wert Else ProcedureReturn #ERROR EndIf EndProcedure Procedure.s Show_mileage_2(*ubMileage) Protected *mileage, mileage.l, a.i, Text.s Text = #Null$ *mileage = *ubMileage For a = 0 To 3 : Text + RSet(Hex(PeekA(*Mileage)), 2, "0") + " " : *Mileage + 1 : Next a mileage = calc_mileage_2(*ubMileage) If mileage = #ERROR ProcedureReturn Text + "--> Crc And/Or Parity Error" Else ProcedureReturn Text + "--> " + StrF( mileage / 100.0, 2) + " km --> CRC OK" EndIf EndProcedure Procedure CheckAllBinFilesInProgramDirectory(sDir.s) Protected hDir.i, hFile.i, *mem hDir = ExamineDirectory(#PB_Any, sDir, "*.bin") If hDir While NextDirectoryEntry(hDir) PrintN(DirectoryEntryName(hDir)) hFile = ReadFile(#PB_Any, (sDir + DirectoryEntryName(hDir))) If hFile *mem = AllocateMemory(20) If *mem FileSeek(hFile, $774) If ReadData(hFile, *mem, 20) = 20 PrintN("0x774: " + Show_mileage_1(*mem)) EndIf FileSeek(hFile, $788) If ReadData(hFile, *mem, 4) = 4 PrintN("0x788: " + Show_mileage_2(*mem)) EndIf FreeMemory(*mem) EndIf CloseFile(hFile) EndIf PrintN("") Wend FinishDirectory(hDir) EndIf EndProcedure If OpenConsole() CheckAllBinFilesInProgramDirectory(GetCurrentDirectory()) PrintN("Press ENTER") Input() CloseConsole() EndIf End ; IDE Options = PureBasic 5.60 (Windows - x64) ; CursorPosition = 188 ; FirstLine = 188 ; Folding = -- ; EnableXP ; Executable = ford_test_x64.exe ; CompileSourceDirectory