-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathecu-19.go
128 lines (102 loc) · 2.7 KB
/
ecu-19.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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
package main
import (
"fmt"
"time"
"errors"
"encoding/hex"
"github.com/distributed/sers"
)
var (
ecu19SpecificInitCommand = []byte {0x7C}
ecu19WokeResponse = []byte {0x55, 0x76, 0x83}
ecu19SpecificInitResponse = []byte {ecu19SpecificInitCommand[0], 0xE9} // includes our echo
)
func readFirstBytesFromPortEcu19(fn string) ([]byte, error) {
fmt.Println("Connecting to MEMS 1.9 ECU")
globalConnected = false
sp, err := sers.Open(fn)
if err != nil {
return nil, err
}
defer sp.Close()
err = sp.SetMode(9600, 8, sers.N, 1, sers.NO_HANDSHAKE)
if err != nil {
return nil, err
}
// setting:
// minread = 0: minimal buffering on read, return characters as early as possible
// timeout = 1.0: time out if after 1.0 seconds nothing is received
err = sp.SetReadParams(0, 0.001)
if err != nil {
return nil, err
}
mode, err := sp.GetMode()
fmt.Println("Serial cable set to:")
fmt.Println(mode)
// try the normal method first
ecu1xLoop(sp, true)
// clear the line
sp.SetBreak(false)
time.Sleep(2000 * time.Millisecond)
start := time.Now()
// start bit
sp.SetBreak(true)
sleepUntil(start, 200)
// send the byte
ecuAddress := 0x16
for i:=0; i<8; i++ {
bit := (ecuAddress >> i) & 1;
if (bit > 0) {
sp.SetBreak(false)
} else {
sp.SetBreak(true)
}
sleepUntil(start, 200 + ((i+1)*200))
}
// stop bit
sp.SetBreak(false)
sleepUntil(start, 200 + (8*200) + 200)
buffer := make([]byte, 0)
readLoops := 0
readLoopsLimit := 200
for readLoops < readLoopsLimit {
readLoops++
if readLoops > 1 {
time.Sleep(10 * time.Millisecond)
}
rb := make([]byte, 128)
n, _ := sp.Read(rb[:])
rb = rb[0:n] // chop down to actual data size
buffer = append(buffer, rb...)
if n > 0 {
readLoops = 0 // reset timeout
}
// clear leading zeros (from our wake up)
for len(buffer) > 0 && buffer[0] == 0x00 {
buffer = buffer[1:]
}
if len(buffer) == 0 { continue }
if slicesEqual(buffer, ecu19WokeResponse) {
fmt.Println("1.9 ECU woke up - init stage 1")
buffer = nil
time.Sleep(50 * time.Millisecond) // TODO: is this the right sleep?
// todo: invert (xor) byte 2 (x83) and send back to ecu
// 0x83, 1000 0011 -> 0x7C 0111 1100
// doing manually for now (doesn't hurt)
sp.Write(ecu19SpecificInitCommand)
continue
}
if slicesEqual(buffer, ecu19SpecificInitResponse) {
fmt.Println("1.9 ECU init stage 2")
buffer = nil
ecu1xLoop(sp, true)
continue
}
}
if readLoops >= readLoopsLimit {
fmt.Printf("1.9 had buffer data: got %d bytes \n%s", len(buffer), hex.Dump(buffer))
return nil, errors.New("MEMS 1.9 timed out")
}
fmt.Println("fell out of 1.9 readloop")
return nil, err
}