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
|
package main
import (
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 uint32 = 0x1272100
sigCtrlMask uint32 = 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 {
req := SignalControlRequest{sig.index}
reply := &SignalDef{}
isReply := func(reply *SignalDef) bool { return true }
return sendCtrlFrame(sig, req, reply, bus, isReply, verifySigCtrlReply)
}
// Verify that the response to a Signal Control REMOTE REQUEST
// is the same as what was commanded to be written.
func verifySigCtrlReply(cmd SignalDef, reply *SignalDef) bool {
reply.index = cmd.index // ignore index and name of reply
reply.name = cmd.name
return *reply == cmd
}
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("wrong DLC for Signal Control frame: %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
}
// SignalControlRequest is a Signal Control REMOTE REQUEST frame.
type SignalControlRequest struct {
sigIndex uint8
}
func (r SignalControlRequest) MarshalFrame() (can.Frame, error) {
return can.Frame{
ID: sigCtrlId | uint32(r.sigIndex&0xF),
IsRemote: true,
IsExtended: true,
}, nil
}
|