forked from acd/infinitive
-
Notifications
You must be signed in to change notification settings - Fork 1
/
frame.go
112 lines (94 loc) · 1.87 KB
/
frame.go
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
package main
import (
"bytes"
"encoding/binary"
"fmt"
"github.com/npat-efault/crc16"
)
const (
opRESPONSE = uint8(0x06)
opREAD = uint8(0x0b)
opWRITE = uint8(0x0c)
opERROR = uint8(0x15)
)
var crcConfig = &crc16.Conf{
Poly: 0x8005, BitRev: true,
IniVal: 0x0, FinVal: 0x0,
BigEnd: false,
}
type InfinityFrame struct {
dst uint16
src uint16
dataLen uint8
op uint8
data []byte
}
var writeAck = &InfinityFrame{
src: devSAM,
dst: devTSTAT,
op: opRESPONSE,
data: []byte{0x00},
}
func checksum(b []byte) []byte {
s := crc16.New(crcConfig)
s.Write(b)
return s.Sum(nil)
}
func (f *InfinityFrame) String() string {
return fmt.Sprintf("%x -> %x: %-8s %x", f.src, f.dst, f.opString(), f.data)
}
func (f *InfinityFrame) opString() string {
switch f.op {
case opRESPONSE:
return "RESPONSE"
case opREAD:
return "READ"
case opWRITE:
return "WRITE"
case opERROR:
return "ERROR"
default:
return fmt.Sprintf("UNKNOWN(%x)", f.op)
}
}
func (frame *InfinityFrame) encode() []byte {
// b := make([]byte, 10 + len(frame.data))
if len(frame.data) > 255 {
panic("frame data too large")
}
var b bytes.Buffer
binary.Write(&b, binary.BigEndian, frame.dst)
binary.Write(&b, binary.BigEndian, frame.src)
b.WriteByte(byte(len(frame.data)))
b.WriteByte(0)
b.WriteByte(0)
b.WriteByte(frame.op)
b.Write(frame.data)
cksum := checksum(b.Bytes())
b.Write(cksum)
return b.Bytes()
}
func (f *InfinityFrame) decode(buf []byte) bool {
nonzero := false
for _, c := range buf {
if c != 0 {
nonzero = true
break
}
}
if !nonzero {
return false
}
l := len(buf) - 2
cksum := checksum(buf[:l])
if !bytes.Equal(cksum, buf[l:]) {
return false
}
f.dst = binary.BigEndian.Uint16(buf[0:2])
f.src = binary.BigEndian.Uint16(buf[2:4])
f.dataLen = buf[4]
// Not sure what bytes 5 and 6 are
f.op = buf[7]
f.data = buf[8:l]
return true
}