diff --git a/src/examples/hid-joystick/main.go b/src/examples/hid-joystick/main.go index 1271d997..755500c9 100644 --- a/src/examples/hid-joystick/main.go +++ b/src/examples/hid-joystick/main.go @@ -2,7 +2,7 @@ package main import ( "log" - "machine/usb/joystick" + "machine/usb/hid/joystick" "math" "time" ) diff --git a/src/machine/usb/hid/hid.go b/src/machine/usb/hid/hid.go index d0ad366f..67656962 100644 --- a/src/machine/usb/hid/hid.go +++ b/src/machine/usb/hid/hid.go @@ -50,6 +50,8 @@ func handler() { } } +var DefaultSetupHandler = setupHandler + func setupHandler(setup usb.Setup) bool { ok := false if setup.BmRequestType == usb.SET_REPORT_TYPE && setup.BRequest == usb.SET_IDLE { diff --git a/src/machine/usb/hid/joystick/joystick.go b/src/machine/usb/hid/joystick/joystick.go new file mode 100644 index 00000000..ed6f712a --- /dev/null +++ b/src/machine/usb/hid/joystick/joystick.go @@ -0,0 +1,77 @@ +package joystick + +import ( + "machine" + "machine/usb" + "machine/usb/hid" +) + +var Joystick *joystick + +type joystick struct { + State + buf *hid.RingBuffer + waitTxc bool + rxHandlerFunc func(b []byte) + setupFunc func(setup usb.Setup) bool +} + +func init() { + if Joystick == nil { + Joystick = newJoystick() + } +} + +func newJoystick() *joystick { + def := DefaultDefinitions() + js := &joystick{ + State: def.NewState(), + buf: hid.NewRingBuffer(), + } + machine.EnableJoystick(js.handler, js.rxHandler, hid.DefaultSetupHandler, def.Descriptor()) + return js +} + +// Port returns the USB Joystick port. +func Port() *joystick { + return Joystick +} + +func (m *joystick) handler() { + m.waitTxc = false + if b, ok := m.buf.Get(); ok { + m.waitTxc = true + hid.SendUSBPacket(b) + } +} + +func (m *joystick) tx(b []byte) { + if machine.USBDev.InitEndpointComplete { + if m.waitTxc { + m.buf.Put(b) + } else { + m.waitTxc = true + hid.SendUSBPacket(b) + } + } +} + +func (m *joystick) ready() bool { + return true +} + +func (m *joystick) rxHandler(b []byte) { + if m.rxHandlerFunc != nil { + m.rxHandlerFunc(b) + } +} + +// to InterruptOut +func (m *joystick) SendReport(reportID byte, b []byte) { + m.tx(append([]byte{reportID}, b...)) +} + +func (m *joystick) SendState() { + b, _ := m.State.MarshalBinary() + m.tx(b) +} diff --git a/src/machine/usb/joystick/state.go b/src/machine/usb/hid/joystick/state.go similarity index 100% rename from src/machine/usb/joystick/state.go rename to src/machine/usb/hid/joystick/state.go diff --git a/src/machine/usb/joystick/buffer.go b/src/machine/usb/joystick/buffer.go deleted file mode 100644 index 3610b52e..00000000 --- a/src/machine/usb/joystick/buffer.go +++ /dev/null @@ -1,52 +0,0 @@ -package joystick - -import ( - "runtime/volatile" -) - -const bufferSize = 32 - -// RingBuffer is ring buffer implementation inspired by post at -// https://www.embeddedrelated.com/showthread/comp.arch.embedded/77084-1.php -type RingBuffer struct { - rxbuffer [bufferSize][16]byte - head volatile.Register8 - tail volatile.Register8 -} - -// NewRingBuffer returns a new ring buffer. -func NewRingBuffer() *RingBuffer { - return &RingBuffer{} -} - -// Used returns how many bytes in buffer have been used. -func (rb *RingBuffer) Used() uint8 { - return uint8(rb.head.Get() - rb.tail.Get()) -} - -// Put stores a byte in the buffer. If the buffer is already -// full, the method will return false. -func (rb *RingBuffer) Put(val []byte) bool { - if rb.Used() != bufferSize { - rb.head.Set(rb.head.Get() + 1) - copy(rb.rxbuffer[rb.head.Get()%bufferSize][:], val) - return true - } - return false -} - -// Get returns a byte from the buffer. If the buffer is empty, -// the method will return a false as the second value. -func (rb *RingBuffer) Get() ([]byte, bool) { - if rb.Used() != 0 { - rb.tail.Set(rb.tail.Get() + 1) - return rb.rxbuffer[rb.tail.Get()%bufferSize][:], true - } - return nil, false -} - -// Clear resets the head and tail pointer to zero. -func (rb *RingBuffer) Clear() { - rb.head.Set(0) - rb.tail.Set(0) -} diff --git a/src/machine/usb/joystick/joystick.go b/src/machine/usb/joystick/joystick.go deleted file mode 100644 index d672cbce..00000000 --- a/src/machine/usb/joystick/joystick.go +++ /dev/null @@ -1,97 +0,0 @@ -package joystick - -import ( - "machine" - "machine/usb" -) - -const ( - jsEndpointOut = usb.HID_ENDPOINT_OUT // from PC - jsEndpointIn = usb.HID_ENDPOINT_IN // to PC -) - -var js *Joystick - -type Joystick struct { - State - buf *RingBuffer - waitTxc bool - rxHandlerFunc func(b []byte) - setupFunc func(setup usb.Setup) bool -} - -func Enable(def Definitions, rxHandlerFunc func(b []byte), - setupFunc func(setup usb.Setup) bool, hidDesc []byte) *Joystick { - m := &Joystick{ - buf: NewRingBuffer(), - State: def.NewState(), - } - m.State = def.NewState() - if setupFunc == nil { - setupFunc = m.setupFunc - } - machine.EnableJoystick(m.handler, rxHandlerFunc, setupFunc, hidDesc) - js = m - return m -} - -// Port returns the USB Joystick port. -func Port() *Joystick { - if js == nil { - def := DefaultDefinitions() - js = &Joystick{ - State: def.NewState(), - buf: NewRingBuffer(), - } - machine.EnableJoystick(js.handler, nil, js.setupFunc, def.Descriptor()) - } - return js -} - -func (m *Joystick) sendUSBPacket(b []byte) { - machine.SendUSBInPacket(jsEndpointIn, b) -} - -// from InterruptIn -func (m *Joystick) handler() { - m.waitTxc = false - if b, ok := m.buf.Get(); ok { - m.waitTxc = true - m.sendUSBPacket(b) - } -} - -func (m *Joystick) setup(setup usb.Setup) bool { - if setup.BmRequestType == usb.SET_REPORT_TYPE && setup.BRequest == usb.SET_IDLE { - machine.SendZlp() - return true - } - return false -} - -func (m *Joystick) rxHandler(b []byte) { - if m.rxHandlerFunc != nil { - m.rxHandlerFunc(b) - } -} - -func (m *Joystick) tx(b []byte) { - if machine.USBDev.InitEndpointComplete { - if m.waitTxc { - m.buf.Put(b) - } else { - m.waitTxc = true - m.sendUSBPacket(b) - } - } -} - -// to InterruptOut -func (m *Joystick) SendReport(reportID byte, b []byte) { - m.tx(append([]byte{reportID}, b...)) -} - -func (m *Joystick) SendState() { - b, _ := m.State.MarshalBinary() - m.tx(b) -}