mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-10 22:13:39 +00:00
175 lines
3.5 KiB
Go
175 lines
3.5 KiB
Go
package joystick
|
|
|
|
import (
|
|
"machine/usb/descriptor"
|
|
|
|
"encoding/binary"
|
|
)
|
|
|
|
type HatDirection uint8
|
|
|
|
const (
|
|
HatUp HatDirection = iota
|
|
HatRightUp
|
|
HatRight
|
|
HatRightDown
|
|
HatDown
|
|
HatLeftDown
|
|
HatLeft
|
|
HatLeftUp
|
|
HatCenter
|
|
)
|
|
|
|
type Constraint struct {
|
|
MinIn int
|
|
MaxIn int
|
|
MinOut int16
|
|
MaxOut int16
|
|
}
|
|
|
|
type AxisValue struct {
|
|
constraint Constraint
|
|
Value int
|
|
}
|
|
|
|
func fit(x, in_min, in_max int, out_min, out_max int16) int16 {
|
|
return int16((x-in_min)*(int(out_max)-int(out_min))/(in_max-in_min) + int(out_min))
|
|
}
|
|
|
|
func fitf(x, in_min, in_max, out_min, out_max float32) float32 {
|
|
return x - in_min*(out_max-out_min)/(in_max-in_min) + out_min
|
|
}
|
|
|
|
func limit(v, max int) int {
|
|
if v > max {
|
|
v = max
|
|
} else if v < -max {
|
|
v = -max
|
|
}
|
|
return v
|
|
}
|
|
|
|
type Definitions struct {
|
|
ReportID byte
|
|
ButtonCnt int
|
|
HatSwitchCnt int
|
|
AxisDefs []Constraint
|
|
descriptor []byte
|
|
}
|
|
|
|
func (c Definitions) Descriptor() []byte {
|
|
if len(c.descriptor) > 0 {
|
|
return c.descriptor
|
|
}
|
|
// TODO: build hid descriptor
|
|
return nil
|
|
}
|
|
|
|
func (c Definitions) NewState() State {
|
|
bufSize := 1
|
|
hatSwitches := make([]HatDirection, c.HatSwitchCnt)
|
|
for i := range hatSwitches {
|
|
hatSwitches[i] = HatCenter
|
|
}
|
|
axises := make([]*AxisValue, 0, len(c.AxisDefs))
|
|
for _, v := range c.AxisDefs {
|
|
|
|
axises = append(axises, &AxisValue{
|
|
constraint: v,
|
|
Value: 0,
|
|
})
|
|
}
|
|
btnSize := (c.ButtonCnt + 7) / 8
|
|
bufSize += btnSize
|
|
bufSize += (len(hatSwitches) + 1) / 2
|
|
bufSize += len(axises) * 2
|
|
initBuf := make([]byte, bufSize)
|
|
initBuf[0] = c.ReportID
|
|
return State{
|
|
buf: initBuf,
|
|
Buttons: make([]byte, btnSize),
|
|
HatSwitches: hatSwitches,
|
|
Axises: axises,
|
|
}
|
|
}
|
|
|
|
type State struct {
|
|
buf []byte
|
|
Buttons []byte
|
|
HatSwitches []HatDirection
|
|
Axises []*AxisValue
|
|
}
|
|
|
|
func (s State) MarshalBinary() ([]byte, error) {
|
|
s.buf = s.buf[0:1]
|
|
s.buf = append(s.buf, s.Buttons...)
|
|
if len(s.HatSwitches) > 0 {
|
|
hat := byte(0)
|
|
for i, v := range s.HatSwitches {
|
|
if i != 0 && i%2 == 0 {
|
|
s.buf = append(s.buf, hat)
|
|
hat = 0
|
|
}
|
|
hat <<= 4
|
|
hat |= byte(v & 0xf)
|
|
}
|
|
s.buf = append(s.buf, hat)
|
|
}
|
|
for _, v := range s.Axises {
|
|
c := v.constraint
|
|
val := fit(v.Value, c.MinIn, c.MaxIn, c.MinOut, c.MaxOut)
|
|
s.buf = binary.LittleEndian.AppendUint16(s.buf, uint16(val))
|
|
}
|
|
return s.buf, nil
|
|
}
|
|
|
|
func (s State) Button(index int) bool {
|
|
idx := index / 8
|
|
bit := uint8(1 << (index % 8))
|
|
return s.Buttons[idx]&bit > 0
|
|
}
|
|
|
|
func (s State) SetButton(index int, push bool) {
|
|
idx := index / 8
|
|
bit := uint8(1 << (index % 8))
|
|
b := s.Buttons[idx]
|
|
b &= ^bit
|
|
if push {
|
|
b |= bit
|
|
}
|
|
s.Buttons[idx] = b
|
|
}
|
|
|
|
func (s State) Hat(index int) HatDirection {
|
|
return s.HatSwitches[index]
|
|
}
|
|
|
|
func (s State) SetHat(index int, dir HatDirection) {
|
|
s.HatSwitches[index] = dir
|
|
}
|
|
|
|
func (s State) Axis(index int) int {
|
|
return s.Axises[index].Value
|
|
}
|
|
|
|
func (s State) SetAxis(index int, v int) {
|
|
s.Axises[index].Value = v
|
|
}
|
|
|
|
func DefaultDefinitions() Definitions {
|
|
return Definitions{
|
|
ReportID: 1,
|
|
ButtonCnt: 16,
|
|
HatSwitchCnt: 1,
|
|
AxisDefs: []Constraint{
|
|
{MinIn: -32767, MaxIn: 32767, MinOut: -32767, MaxOut: 32767},
|
|
{MinIn: -32767, MaxIn: 32767, MinOut: -32767, MaxOut: 32767},
|
|
{MinIn: -32767, MaxIn: 32767, MinOut: -32767, MaxOut: 32767},
|
|
{MinIn: -32767, MaxIn: 32767, MinOut: -32767, MaxOut: 32767},
|
|
{MinIn: -32767, MaxIn: 32767, MinOut: -32767, MaxOut: 32767},
|
|
{MinIn: -32767, MaxIn: 32767, MinOut: -32767, MaxOut: 32767},
|
|
},
|
|
descriptor: descriptor.JoystickDefaultHIDReport,
|
|
}
|
|
}
|