98 lines
2.3 KiB
Go
98 lines
2.3 KiB
Go
package mappingrules
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
|
|
"git.annabunches.net/annabunches/joyful/internal/configparser"
|
|
"github.com/holoplot/go-evdev"
|
|
)
|
|
|
|
// TODO: need tests for multiple deadzones
|
|
// TODO: need tests for emitting deadzones
|
|
|
|
type Deadzone struct {
|
|
Start int32
|
|
End int32
|
|
Size int32
|
|
Emit bool
|
|
EmitValue int32
|
|
}
|
|
|
|
// DeadzoneState indicates whether a value is in a Deadzone and, if it is, whether the deadzone
|
|
// should emit an event
|
|
type DeadzoneState int
|
|
|
|
const (
|
|
// DeadzoneClear indicates the value is *not* in the deadzone.
|
|
DeadzoneClear DeadzoneState = iota
|
|
DeadzoneEmit
|
|
DeadzoneNoEmit
|
|
)
|
|
|
|
// calculateDeadzones produces the deadzone start and end values in absolute terms
|
|
func NewDeadzoneFromConfig(dzConfig configparser.DeadzoneConfig, device Device, axis evdev.EvCode) (Deadzone, error) {
|
|
dz := Deadzone{}
|
|
dz.Emit = dzConfig.Emit
|
|
dz.EmitValue = dzConfig.Value
|
|
|
|
var min, max int32
|
|
absInfoMap, err := device.AbsInfos()
|
|
|
|
if err != nil {
|
|
return dz, err
|
|
} else {
|
|
absInfo := absInfoMap[axis]
|
|
min = absInfo.Minimum
|
|
max = absInfo.Maximum
|
|
}
|
|
|
|
if dzConfig.Start != 0 || dzConfig.End != 0 {
|
|
dz.Start = Clamp(dzConfig.Start, min, max)
|
|
dz.End = Clamp(dzConfig.End, min, max)
|
|
if dz.Start > dz.End {
|
|
return dz, errors.New("deadzone end must be greater than deadzone start")
|
|
}
|
|
} else {
|
|
center := Clamp(dzConfig.Center, min, max)
|
|
var deadzoneSize int32
|
|
|
|
switch {
|
|
case dzConfig.Size != 0:
|
|
deadzoneSize = dzConfig.Size
|
|
case dzConfig.SizePercent != 0:
|
|
deadzoneSize = (max - min) / dzConfig.SizePercent
|
|
default:
|
|
return dz, fmt.Errorf("deadzone configured incorrectly; must define start and end or center and size")
|
|
}
|
|
|
|
dz.Start = center - deadzoneSize/2
|
|
dz.End = center + deadzoneSize/2
|
|
dz.Start, dz.End = clampAndShift(dz.Start, dz.End, min, max)
|
|
}
|
|
|
|
dz.Size = dz.End - dz.Start
|
|
return dz, nil
|
|
}
|
|
|
|
func CalculateDeadzoneSize(dzs []Deadzone) int32 {
|
|
var size int32
|
|
|
|
for _, dz := range dzs {
|
|
size += dz.Size
|
|
}
|
|
|
|
return size
|
|
}
|
|
|
|
// Match checks whether the target value is inside the deadzone.
|
|
// It returns a DeadzoneState enum and possibly an int32.
|
|
func (dz Deadzone) Match(value int32) (DeadzoneState, int32) {
|
|
if value < dz.Start || value > dz.End {
|
|
return DeadzoneClear, value
|
|
}
|
|
if dz.Emit {
|
|
return DeadzoneEmit, dz.EmitValue
|
|
}
|
|
return DeadzoneNoEmit, value
|
|
}
|