Created
March 20, 2023 14:20
-
-
Save aravindanve/bf6c663c3f6b33055873f847cad49a73 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
// This script reads a modified fit file (source.fit) and computes the correct | |
// crc16 value and writes the output to a new file (output.fit) | |
import ( | |
"encoding/binary" | |
"encoding/hex" | |
"fmt" | |
"io" | |
"log" | |
"os" | |
"strconv" | |
) | |
// https://developer.garmin.com/fit/protocol/#crc | |
func getFitCRC16(crc uint16, b uint8) uint16 { | |
var crc_table = []uint16{ | |
0x0000, 0xCC01, 0xD801, 0x1400, 0xF001, 0x3C00, 0x2800, 0xE401, | |
0xA001, 0x6C00, 0x7800, 0xB401, 0x5000, 0x9C01, 0x8801, 0x4400, | |
} | |
var tmp uint16 | |
// compute checksum of lower four bits of byte | |
tmp = crc_table[crc&0xF] | |
crc = (crc >> 4) & 0x0FFF | |
crc = crc ^ tmp ^ crc_table[b&0xF] | |
// now compute checksum of upper four bits of byte | |
tmp = crc_table[crc&0xF] | |
crc = (crc >> 4) & 0x0FFF | |
crc = crc ^ tmp ^ crc_table[(b>>4)&0xF] | |
return crc | |
} | |
func main() { | |
// open source src | |
// source.fit is the modified fit file with bad crc | |
src, err := os.Open("source.fit") | |
if err != nil { | |
fmt.Println("Error opening source file! " + err.Error()) | |
} | |
defer src.Close() | |
srcStat, err := src.Stat() | |
if err != nil { | |
fmt.Println("Error reading source file! " + err.Error()) | |
} | |
srcSize := srcStat.Size() | |
srcCrcB := []byte{} | |
outSize := int64(0) | |
// open output file | |
// output.fit is the modified fit file with computed crc | |
out, err := os.Create("output.fit") | |
if err != nil { | |
fmt.Println("Error opening output file! " + err.Error()) | |
} | |
defer out.Close() | |
// create buffer | |
buf := make([]byte, 1) | |
var crc uint16 | |
for { | |
_, err := src.Read(buf) | |
if err != nil { | |
if err != io.EOF { | |
log.Fatal(err) | |
} | |
break | |
} | |
// only process bytes before crc | |
if outSize < srcSize-2 { | |
_, err = out.Write(buf) | |
if err != nil { | |
log.Fatal(err) | |
} | |
crc = getFitCRC16(crc, buf[0]) | |
outSize++ | |
} else { | |
srcCrcB = append(srcCrcB, buf[0]) | |
} | |
} | |
outCrcB := []byte{} | |
outCrcB = binary.LittleEndian.AppendUint16(outCrcB, crc) | |
// write crc to output | |
_, err = out.Write(outCrcB) | |
if err != nil { | |
log.Fatal(err) | |
} | |
outSize += 2 | |
fmt.Println("src size: " + strconv.FormatInt(srcSize, 10)) | |
fmt.Println("src crc16: " + hex.EncodeToString(srcCrcB)) | |
fmt.Println("out size: " + strconv.FormatInt(outSize, 10)) | |
fmt.Println("out crc16: " + hex.EncodeToString(outCrcB)) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment