|
@@ -10,7 +10,6 @@ import (
|
|
|
)
|
|
|
|
|
|
const (
|
|
|
- gamepadChanBufSize = 16
|
|
|
// Logitech gamepad codes
|
|
|
codeLeftAnalogX = 0
|
|
|
codeLeftAnalogY = 1
|
|
@@ -31,6 +30,9 @@ const (
|
|
|
codeLogitech = 316
|
|
|
codeLeftAnalog = 317
|
|
|
codeRightAnalog = 318
|
|
|
+)
|
|
|
+
|
|
|
+const (
|
|
|
// event types
|
|
|
button = iota
|
|
|
axisX
|
|
@@ -38,6 +40,8 @@ const (
|
|
|
axisZ
|
|
|
)
|
|
|
|
|
|
+const gamepadChanBufSize = 16
|
|
|
+
|
|
|
type event struct {
|
|
|
code int
|
|
|
value int32
|
|
@@ -65,14 +69,49 @@ type gamepadEvents struct {
|
|
|
back, start, logitech chan event
|
|
|
}
|
|
|
|
|
|
+const (
|
|
|
+ // drive modes
|
|
|
+ tank = iota
|
|
|
+ joystick
|
|
|
+)
|
|
|
+
|
|
|
+const driveModeCount = 2
|
|
|
+
|
|
|
+type driveMode int
|
|
|
+
|
|
|
+func (d driveMode) String() string {
|
|
|
+ switch d {
|
|
|
+ case tank:
|
|
|
+ return "tank"
|
|
|
+ case joystick:
|
|
|
+ return "joystick"
|
|
|
+ default:
|
|
|
+ return "unknown"
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func (d *driveMode) Set(value string) error {
|
|
|
+ switch value {
|
|
|
+ case "tank":
|
|
|
+ *d = tank
|
|
|
+ case "joystick":
|
|
|
+ *d = joystick
|
|
|
+ default:
|
|
|
+ return fmt.Errorf("unknown drive mode: %v", value)
|
|
|
+ }
|
|
|
+ return nil
|
|
|
+}
|
|
|
+
|
|
|
func main() {
|
|
|
var (
|
|
|
gamepad string
|
|
|
listen string
|
|
|
+ mode driveMode
|
|
|
)
|
|
|
|
|
|
flag.StringVar(&gamepad, "gamepad", "/dev/input/event0", "the gamepad device path")
|
|
|
flag.StringVar(&listen, "listen", "localhost:8080", "the HTTP listen address and port")
|
|
|
+ flag.Var(&mode, "mode", "the drive mode (default \"tank\")")
|
|
|
flag.Parse()
|
|
|
|
|
|
if !evdev.IsInputDevice(gamepad) {
|
|
@@ -98,13 +137,15 @@ func main() {
|
|
|
logitech: make(chan event, gamepadChanBufSize),
|
|
|
}
|
|
|
|
|
|
- go control(events)
|
|
|
+ go control(mode, events)
|
|
|
go gamepadRead(device, events)
|
|
|
|
|
|
+ log.Print("HTTP server started")
|
|
|
log.Fatalf("error listening and serving: %v", http.ListenAndServe(listen, nil))
|
|
|
}
|
|
|
|
|
|
-func control(events *gamepadEvents) {
|
|
|
+func control(mode driveMode, events *gamepadEvents) {
|
|
|
+ log.Printf("control loop started (drive mode: %v)", mode)
|
|
|
for {
|
|
|
select {
|
|
|
case e := <-events.leftAnalog:
|
|
@@ -130,12 +171,17 @@ func control(events *gamepadEvents) {
|
|
|
case e := <-events.start:
|
|
|
log.Println("start", e)
|
|
|
case e := <-events.logitech:
|
|
|
- log.Println("logitech", e)
|
|
|
+ if e.value > 0 {
|
|
|
+ mode++
|
|
|
+ mode %= driveModeCount
|
|
|
+ log.Printf("switched drive mode: %v", mode)
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
func gamepadRead(device *evdev.InputDevice, events *gamepadEvents) {
|
|
|
+ log.Print("gamepad read loop started")
|
|
|
for {
|
|
|
e, err := device.ReadOne()
|
|
|
if err != nil {
|