-
Notifications
You must be signed in to change notification settings - Fork 4
/
switchpanel.go
160 lines (147 loc) · 3.79 KB
/
switchpanel.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
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
156
157
158
159
160
package fpanels
import (
"sync"
"github.com/google/gousb"
)
// Switch panel switches
const (
SwBat SwitchID = iota
SwAlternator
SwAvionics
SwFuel
SwDeice
SwPitot
SwCowl
SwPanel
SwBeacon
SwNav
SwStrobe
SwTaxi
SwLanding
RotOff
RotR
RotL
RotBoth
RotStart
GearUp
GearDown
)
// Switch panel landing gear lights
const (
LEDNGreen byte = 1 << iota
LEDLGreen
LEDRGreen
LEDNRed
LEDLRed
LEDRRed
LEDNYellow = LEDNGreen | LEDNRed
LEDLYellow = LEDLGreen | LEDLRed
LEDRYellow = LEDRGreen | LEDRRed
LEDAllGreen = LEDNGreen | LEDLGreen | LEDRGreen
LEDAllRed = LEDNRed | LEDLRed | LEDRRed
LEDAllYellow = LEDNYellow | LEDLYellow | LEDRYellow
LEDNAll = LEDNYellow
LEDLAll = LEDLYellow
LEDRAll = LEDRYellow
LEDAll = LEDAllYellow
)
// SwitchPanel represents a Saitek/Logitech switch panel. The panel has:
//
// - A five position switch
//
// - Thirteen two position switches
//
// - A two position landing gear lever
//
// - Three red/green landing gear indicator LEDs
type SwitchPanel struct {
panel
}
// NewSwitchPanel create a new instance of the Logitech/Saitek switch panel
func NewSwitchPanel() (*SwitchPanel, error) {
var err error
panel := SwitchPanel{}
panel.id = Switch
panel.displayState = make([]byte, 1)
panel.displayState[0] = 0
panel.displayDirty = true
panel.displayCond = sync.NewCond(&panel.displayMutex)
panel.ctx = gousb.NewContext()
panel.device, err = panel.ctx.OpenDeviceWithVIDPID(USBVendorPanel, USBProductSwitch)
if panel.device == nil || err != nil {
panel.Close()
return nil, err
}
panel.device.SetAutoDetach(true)
panel.intf, panel.intfDone, err = panel.device.DefaultInterface()
if err != nil {
panel.Close()
return nil, err
}
panel.inEndpoint, err = panel.intf.InEndpoint(1)
if err != nil {
panel.Close()
return nil, err
}
// FIX: Add WaitGroup
panel.switchCh = make(chan SwitchState)
go panel.readSwitches()
go panel.refreshDisplay()
panel.connected = true
return &panel, nil
}
// LEDs turns on/off the LEDs given by leds. See the LED* constants.
// For example calling
// panel.LEDs(LEDLGreen | LEDRGreen)
// will turn on the left and right green landing gear LEDs and turn off
// all other LEDs
func (panel *SwitchPanel) LEDs(leds byte) {
panel.displayMutex.Lock()
panel.displayState[0] = leds
panel.displayDirty = true
panel.displayCond.Signal()
panel.displayMutex.Unlock()
}
// LEDsOn turns on the ELDS given by leds and leaves the other LED states
// intact. See the switch panel LED constants. Multiple LEDs can be ORed
// together. For example:
// panel.LEDsOn(LEDLGreen | LEDRGreen)
func (panel *SwitchPanel) LEDsOn(leds byte) {
panel.displayMutex.Lock()
panel.displayState[0] = panel.displayState[0] | leds
panel.displayDirty = true
panel.displayCond.Signal()
panel.displayMutex.Unlock()
}
// LEDsOff turn off the LEDs given by leds and leaves all other LED states
// instact. See the switch panel LED constants. Multiple LEDs can be ORed
// together. For example:
// panel.LEDsOff(LEDLGreen | LEDRGreen)
func (panel *SwitchPanel) LEDsOff(leds byte) {
panel.displayMutex.Lock()
panel.displayState[0] = panel.displayState[0] & ^leds
panel.displayDirty = true
panel.displayCond.Signal()
panel.displayMutex.Unlock()
}
// LEDsOnOff turns on or off the LEDs given by leds. If val is 0 then
// the LEDs will be turned off, else they will be turned on. All other
// LEDs are left intact. See the switch panel LED constants.
// Multiple LEDs can be ORed togethe, for example:
// panel.LEDsOnOff(LEDLGreen | LEDRGreen, 1)
func (panel *SwitchPanel) LEDsOnOff(leds byte, val float64) {
if val > 0 {
panel.LEDsOn(leds)
} else {
panel.LEDsOff(leds)
}
}
func (panel *SwitchPanel) noZeroSwitch(s SwitchID) bool {
if s >= RotOff && s <= RotStart {
return true
}
if s == GearUp || s == GearDown {
return true
}
return false
}