diff options
| -rw-r--r-- | sw/cal/csv.go | 55 | ||||
| -rw-r--r-- | sw/cal/main.go | 54 |
2 files changed, 101 insertions, 8 deletions
diff --git a/sw/cal/csv.go b/sw/cal/csv.go new file mode 100644 index 0000000..bb5cd01 --- /dev/null +++ b/sw/cal/csv.go @@ -0,0 +1,55 @@ +package main + +import ( + "os" + "fmt" + "io" + "strconv" + "encoding/csv" +) + +func parseTable(filename string) (map[int32]uint16, error) { + f, err := os.Open(filename) + if err != nil { + eprintf("%v\n", err) + } + defer f.Close() + + tbl := make(map[int32]uint16) + rdr := csv.NewReader(f) + for { + err := parseRow(rdr, tbl) + if err == io.EOF { + return tbl, nil + } else if err != nil { + return nil, fmt.Errorf("%s:%v", filename, err) + } + } +} + +func parseRow(rdr *csv.Reader, tbl map[int32]uint16) error { + row, err := rdr.Read() + if err != nil { + return err + } + if len(row) != 2 { + line, _ := rdr.FieldPos(0) + return fmt.Errorf("%d: malformed row", line) + } + key, err := strconv.ParseInt(row[0], 10, 32) + if err != nil { + line, col := rdr.FieldPos(0) + return fmt.Errorf("%d:%d: %v", line, col, err) + } + val, err := strconv.ParseUint(row[1], 10, 16) + if err != nil { + line, col := rdr.FieldPos(1) + return fmt.Errorf("%d:%d: %v", line, col, err) + } + if _, ok := tbl[int32(key)]; ok { + line, col := rdr.FieldPos(0) + return fmt.Errorf("%d: %d: duplicate key %d", line, col, key) + } + tbl[int32(key)] = uint16(val) + return nil +} diff --git a/sw/cal/main.go b/sw/cal/main.go index 3758a07..a6e4b1d 100644 --- a/sw/cal/main.go +++ b/sw/cal/main.go @@ -35,7 +35,18 @@ var ( an4Sig = flag.String(an4SigFlag, "", "analog channel 4 signal name") // Calibration tables - // TODO + tachTblFlag = "tachTbl" + speedTblFlag = "speedTbl" + an1TblFlag = "an1Tbl" + an2TblFlag = "an2Tbl" + an3TblFlag = "an3Tbl" + an4TblFlag = "an4Tbl" + tachTbl = flag.String(tachTblFlag, "", "tachometer calibration CSV file") + speedTbl = flag.String(speedTblFlag, "", "speedometer calibration CSV file") + an1Tbl = flag.String(an1TblFlag, "", "analog channel 1 calibration CSV file") + an2Tbl = flag.String(an2TblFlag, "", "analog channel 2 calibration CSV file") + an3Tbl = flag.String(an3TblFlag, "", "analog channel 3 calibration CSV file") + an4Tbl = flag.String(an4TblFlag, "", "analog channel 4 calibration CSV file") ) func main() { @@ -46,23 +57,50 @@ func main() { flag.Usage() os.Exit(1) } + if err := checkTablesProvided(); err != nil { + eprintf("%v\n", err) + } sigNames := nonEmpty(*tachSig, *speedSig, *an1Sig, *an2Sig, *an3Sig, *an4Sig) + tblFilenames := nonEmpty(*tachTbl, *speedTbl, *an1Tbl, *an2Tbl, *an3Tbl, *an4Tbl) // Parse signals in DBC file + fmt.Println("Parsing", *dbcFilename) sigDefs, err := parseSignals(*dbcFilename, sigNames) if err != nil { - eprintf("Error parsing %s: %v\n", *dbcFilename, err) + eprintf("%v\n", err) + } + + // Parse calibration tables + for _, filename := range tblFilenames { + fmt.Println("Parsing", filename) + tbl, err := parseTable(filename) + if err != nil { + eprintf("%v\n", err) + } } fmt.Println(sigDefs) } -func nonEmpty(ss ...string) []string { - r := make([]string, 0, len(ss)) - for _, s := range ss { - if s != "" { - r = append(r, s) +func nonEmpty(ss ...string) map[int]string { + m := make(map[int]string) + for i := range ss { + if ss[i] != "" { + m[i] = ss[i] + } + } + return m +} + +// Check that a calibration table was provided for each given signal. +func checkTablesProvided() error { + signals := []string{*tachSig, *speedSig, *an1Sig, *an2Sig, *an3Sig, *an4Sig} + tables := []string{*tachTbl, *speedTbl, *an1Tbl, *an2Tbl, *an3Tbl, *an4Tbl} + tableFlags := []string{tachTblFlag, speedTblFlag, an1TblFlag, an2TblFlag, an3TblFlag, an4TblFlag} + for i := range signals { + if signals[i] != "" && tables[i] == "" { + return fmt.Errorf("Missing flag -%s", tableFlags[i]) } } - return r + return nil } |