diff options
| author | Sam Anthony <sam@samanthony.xyz> | 2025-11-08 08:41:34 -0500 |
|---|---|---|
| committer | Sam Anthony <sam@samanthony.xyz> | 2025-11-08 08:41:34 -0500 |
| commit | 413d894d0637d7a4e55025664043ffa1c29e9bbb (patch) | |
| tree | cc8a5674c13ee04d39d1e7e4b363bdff1ad47c27 /sw/cal | |
| parent | b9ad4f9701304cd616337fd6df21f6442de743bd (diff) | |
| download | can-gauge-interface-413d894d0637d7a4e55025664043ffa1c29e9bbb.zip | |
cal: wash
Diffstat (limited to 'sw/cal')
| -rw-r--r-- | sw/cal/can.go | 25 | ||||
| -rw-r--r-- | sw/cal/main.go | 63 |
2 files changed, 58 insertions, 30 deletions
diff --git a/sw/cal/can.go b/sw/cal/can.go index e47a42c..751ffd9 100644 --- a/sw/cal/can.go +++ b/sw/cal/can.go @@ -17,25 +17,31 @@ const ( timeout = 5 * time.Second ) -// Write a calibration table to the EEPROM. -func writeTable(tx *socketcan.Transmitter, tbl Table, sig int) error { +// Transmit a table in Table Control frames so the Interface can store it in its EEPROM. +func sendTable(tx *socketcan.Transmitter, tbl Table, sig int) error { + // Send populated rows var i int for i = 0; i < len(tbl.keys); i++ { - err := writeRow(tx, tbl.keys[i], tbl.vals[i], sig, i) + err := sendRow(tx, tbl.keys[i], tbl.vals[i], sig, i) if err != nil { return err } } + + // Fill rest of table with last row for ; i < tabRows; i++ { - err := writeRow(tx, tbl.keys[len(tbl.keys)-1], tbl.vals[len(tbl.keys)-1], sig, i) + err := sendRow(tx, tbl.keys[len(tbl.keys)-1], tbl.vals[len(tbl.keys)-1], sig, i) if err != nil { return err } } + return nil } -func writeRow(tx *socketcan.Transmitter, key int32, val uint16, sig int, row int) error { +// Transmit a Table Control frame containing one row of a table. +func sendRow(tx *socketcan.Transmitter, key int32, val uint16, sig int, row int) error { + // Serialize DATA FIELD var data [8]byte _, err := bin.Encode(data[0:4], bin.BigEndian, key) if err != nil { @@ -46,6 +52,7 @@ func writeRow(tx *socketcan.Transmitter, key int32, val uint16, sig int, row int return err } + // Construct ID and send frame frame := can.Frame{ ID: uint32(tblCtrlId) | uint32((sig<<5)&0xE0) | uint32(row&0x1F), Length: 6, @@ -54,18 +61,18 @@ func writeRow(tx *socketcan.Transmitter, key int32, val uint16, sig int, row int } ctx, _ := context.WithTimeout(context.Background(), timeout) return transmit(tx, frame, ctx) - } +// Transmit a CAN frame to the bus, retrying if the buffer is full. func transmit(tx *socketcan.Transmitter, frame can.Frame, ctx context.Context) error { for { err := tx.TransmitFrame(ctx, frame) if err == nil { - return nil + return nil // success } else if strings.HasSuffix(err.Error(), "no buffer space available") { - continue + continue // retry } else { - return err + return err // error, abort } } } diff --git a/sw/cal/main.go b/sw/cal/main.go index 64b63ca..d87dd64 100644 --- a/sw/cal/main.go +++ b/sw/cal/main.go @@ -66,14 +66,8 @@ func main() { 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("%v\n", err) - } - // Open CAN connection + fmt.Println("Opening connection to", *canDev) conn, err := socketcan.Dial("can", *canDev) if err != nil { eprintf("%v\n", err) @@ -82,23 +76,18 @@ func main() { tx := socketcan.NewTransmitter(conn) defer tx.Close() - // Write calibration tables to EEPROM - for k, filename := range tblFilenames { - fmt.Println("Parsing", filename) - tbl, err := parseTable(filename) - if err != nil { - eprintf("%v\n", err) - } - - fmt.Println("Transmitting", filename) - if err := writeTable(tx, tbl, k); err != nil { - eprintf("%v\n", err) - } + // Parse DBC file and transmit encoding of each signal + if err := sendEncodings(*dbcFilename, sigNames, tx); err != nil { + eprintf("%v\n", err) } - fmt.Println(sigDefs) // TODO + // Parse tables and transmit them + if err := sendTables(tblFilenames, tx); err != nil { + eprintf("%v\n", err) + } } +// Return a map of non-empty strings keyed by their index in the given list. func nonEmpty(ss ...string) map[int]string { m := make(map[int]string) for i := range ss { @@ -109,15 +98,47 @@ func nonEmpty(ss ...string) map[int]string { return m } -// Check that a calibration table was provided for each given signal. +// Check that the user provided a corresponding table for each signal they gave. 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] == "" { + // No corresponding table return fmt.Errorf("Missing flag -%s", tableFlags[i]) } } + return nil // all present signals have a matching table +} + +// Parse DBC file and transmit encoding of each signal using Signal Control frames. +func sendEncodings(dbcFilename string, sigNames map[int]string, tx *socketcan.Transmitter) error { + // Parse DBC file + fmt.Println("Parsing", dbcFilename) + sigDefs, err := parseSignals(dbcFilename, sigNames) + if err != nil { + return err + } + + // Transmit Signal Control frames + + // TODO +} + +// Parse each table and transmit them using Table Control frames. +func sendTables(tblFilenames map[int]string, tx *socketcan.Transmitter) error { + for k, filename := range tblFilenames { + fmt.Println("Parsing", filename) + tbl, err := parseTable(filename) + if err != nil { + return err + } + + fmt.Println("Transmitting", filename) + if err := sendTable(tx, tbl, k); err != nil { + return err + } + } return nil } |