mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-04 19:17:47 +00:00
132 lines
2.2 KiB
Go
132 lines
2.2 KiB
Go
package usb
|
|
|
|
import (
|
|
"errors"
|
|
"runtime/volatile"
|
|
)
|
|
|
|
const QueueSize = 8
|
|
|
|
type Queue struct {
|
|
fifo [QueueSize]uint8
|
|
tail volatile.Register32
|
|
head volatile.Register32
|
|
}
|
|
|
|
var (
|
|
ErrReadBuffer = errors.New("cannot copy into read buffer")
|
|
ErrWriteBuffer = errors.New("cannot copy from write buffer")
|
|
ErrQueueEmpty = errors.New("data queue empty") // Read Error
|
|
ErrQueueFull = errors.New("data queue full") // Write error
|
|
)
|
|
|
|
// Reset discards all buffered data.
|
|
//go:inline
|
|
func (q *Queue) Reset() {
|
|
for i := range q.fifo {
|
|
q.fifo[i] = 0
|
|
}
|
|
q.tail.Set(0)
|
|
q.head.Set(0)
|
|
}
|
|
|
|
//go:inline
|
|
func (q *Queue) Len() int {
|
|
return int(q.tail.Get() - q.head.Get())
|
|
}
|
|
|
|
//go:inline
|
|
func (q *Queue) Cap() int {
|
|
return cap(q.fifo)
|
|
}
|
|
|
|
func (q *Queue) Read(data []uint8) (int, error) {
|
|
|
|
less := uint32(len(data))
|
|
if less == 0 {
|
|
return 0, ErrReadBuffer
|
|
} // nothing to copy into
|
|
|
|
head := q.head.Get()
|
|
used := q.tail.Get() - head
|
|
|
|
if used == 0 {
|
|
return 0, ErrQueueEmpty
|
|
} // empty queue
|
|
|
|
if less > used {
|
|
less = used
|
|
} // only get from used space
|
|
|
|
for i := uint32(0); i < less; i++ {
|
|
data[i] = q.fifo[head%QueueSize]
|
|
head++
|
|
}
|
|
q.head.Set(head)
|
|
|
|
return int(less), nil
|
|
}
|
|
|
|
func (q *Queue) Write(data []uint8) (int, error) {
|
|
|
|
more := uint32(len(data))
|
|
if more == 0 {
|
|
return 0, ErrWriteBuffer
|
|
} // nothing to copy from
|
|
|
|
tail := q.tail.Get()
|
|
used := tail - q.head.Get()
|
|
|
|
if used == QueueSize {
|
|
return 0, ErrQueueFull
|
|
} // full queue
|
|
|
|
if used+more > QueueSize {
|
|
more = QueueSize - used
|
|
} // only put to unused space
|
|
|
|
for i := uint32(0); i < more; i++ {
|
|
q.fifo[tail%QueueSize] = data[i]
|
|
tail++
|
|
}
|
|
q.tail.Set(tail)
|
|
|
|
return int(more), nil
|
|
}
|
|
|
|
func (q *Queue) Deq() (uint8, bool) {
|
|
|
|
tail := q.head.Get()
|
|
if tail == q.tail.Get() {
|
|
return 0, false
|
|
} // empty queue
|
|
|
|
data := q.fifo[tail%QueueSize]
|
|
q.head.Set(tail + 1)
|
|
|
|
return data, true
|
|
}
|
|
|
|
func (q *Queue) Front() (uint8, bool) {
|
|
|
|
tail := q.head.Get()
|
|
if tail == q.tail.Get() {
|
|
return 0, false
|
|
} // empty queue
|
|
|
|
return q.fifo[tail%QueueSize], true
|
|
}
|
|
|
|
func (q *Queue) Enq(data uint8) bool {
|
|
|
|
head := q.tail.Get()
|
|
if head-q.head.Get() == QueueSize {
|
|
return false
|
|
} // full queue
|
|
|
|
q.fifo[head%QueueSize] = data
|
|
q.tail.Set(head + 1)
|
|
|
|
return true
|
|
}
|