1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
|
package main
import (
"context"
bin "encoding/binary"
"fmt"
"math"
"go.einride.tech/can"
"go.einride.tech/can/pkg/dbc"
"git.samanthony.xyz/can_gauge_interface/sw/cal/canbus"
)
const (
sigCtrlId = 0x1272100
sigCtrlMask = 0x1FFFF00
exide = 1 << 31
)
type SignalDef struct {
index uint8
id uint32
isExtended bool
name string
start, size uint8
isBigEndian bool
isSigned bool
}
func NewSignalDef(index uint8, msg *dbc.MessageDef, sig dbc.SignalDef) (SignalDef, error) {
if sig.StartBit > math.MaxUint8 {
return SignalDef{}, fmt.Errorf("%s: start bit out of range: %d", sig.Name, sig.StartBit)
}
if sig.Size > math.MaxUint8 {
return SignalDef{}, fmt.Errorf("%s: size out of range: %d", sig.Name, sig.Size)
}
return SignalDef{
index,
uint32(msg.MessageID) & extMask,
msg.MessageID.IsExtended(),
string(sig.Name),
uint8(sig.StartBit),
uint8(sig.Size),
sig.IsBigEndian,
sig.IsSigned,
}, nil
}
// Transmit a signal's encoding in a Signal Control frame so the Interface can store it in its EEPROM.
func (sig SignalDef) SendEncoding(bus canbus.Bus) error {
frame, err := sig.MarshalFrame()
if err != nil {
return err
}
var retry int
for retry = 0; retry < maxRetries; retry++ {
// Write to EEPROM
ctx, _ := context.WithTimeout(context.Background(), timeout)
if err := bus.Send(ctx, frame); err != nil {
return err
}
// Read back
request := sigCtrlRequest(sig.index)
ctx, _ = context.WithTimeout(context.Background(), timeout)
if err := bus.Send(ctx, request); err != nil {
return err
}
ctx, _ = context.WithTimeout(context.Background(), timeout)
reply, err := bus.Receive(ctx)
if err != nil {
return err
}
var rsig SignalDef
err = rsig.UnmarshalFrame(reply)
if err == errWrongId {
fmt.Println("Wrong ID", reply, "; expected", sigCtrlId)
continue
} else if err != nil {
return err
}
// Verify
rsig.index = sig.index
rsig.name = sig.name
fmt.Println("Received signal encoding", rsig)
if rsig == sig {
fmt.Printf("Signal %d encoding OK\n", sig.index)
return nil // success
} else {
weprintf("Warning: signal %d verification failed; rewriting...\n", sig.index)
continue
}
}
// Max retries exceeded
return fmt.Errorf("signal %d verification failed", sig.index)
}
// Construct a Signal Control REMOTE REQUEST frame.
func sigCtrlRequest(index uint8) can.Frame {
return can.Frame{
ID: sigCtrlId | uint32(index&0xF),
IsRemote: true,
IsExtended: true,
}
}
func (sig SignalDef) MarshalFrame() (can.Frame, error) {
var data [8]byte
if _, err := bin.Encode(data[0:4], bin.BigEndian, uint32(sig.id)&extMask); err != nil {
return can.Frame{}, err
}
if sig.isExtended {
data[0] |= 0x80 // EXIDE
}
data[4] = uint8(sig.start)
data[5] = uint8(sig.size)
if !sig.isBigEndian {
data[6] |= 0x80
}
if sig.isSigned {
data[6] |= 0x40
}
return can.Frame{
ID: sigCtrlId | uint32(sig.index&0xF),
Length: 7,
Data: data,
IsExtended: true,
}, nil
}
func (sig *SignalDef) UnmarshalFrame(frame can.Frame) error {
if !frame.IsExtended || frame.ID&sigCtrlMask != sigCtrlId {
return errWrongId
}
if frame.Length != 7 {
return fmt.Errorf("Signal Control frame has wrong DLC: %d", frame.Length)
}
sig.index = uint8(frame.ID & 0xF)
var id uint32
if _, err := bin.Decode(frame.Data[0:4], bin.BigEndian, &id); err != nil {
return err
}
sig.id = id & extMask
sig.isExtended = id&exide != 0
sig.start = frame.Data[4]
sig.size = frame.Data[5]
sig.isBigEndian = frame.Data[6]&0x80 == 0
sig.isSigned = frame.Data[6]&0x40 != 0
return nil
}
|