github.com/tinygo-org/tinygo@v0.31.3-0.20240404173401-90b0bf646c27/src/machine/usb/adc/midi/buffer.go (about) 1 package midi 2 3 import ( 4 "runtime/volatile" 5 ) 6 7 const bufferSize = 128 8 9 // RingBuffer is ring buffer implementation inspired by post at 10 // https://www.embeddedrelated.com/showthread/comp.arch.embedded/77084-1.php 11 type RingBuffer struct { 12 rxbuffer [bufferSize][4]byte 13 head volatile.Register8 14 tail volatile.Register8 15 } 16 17 // NewRingBuffer returns a new ring buffer. 18 func NewRingBuffer() *RingBuffer { 19 return &RingBuffer{} 20 } 21 22 // Used returns how many bytes in buffer have been used. 23 func (rb *RingBuffer) Used() uint8 { 24 return uint8(rb.head.Get() - rb.tail.Get()) 25 } 26 27 // Put stores a byte in the buffer. If the buffer is already 28 // full, the method will return false. 29 func (rb *RingBuffer) Put(val []byte) bool { 30 if rb.Used() != bufferSize { 31 rb.head.Set(rb.head.Get() + 1) 32 copy(rb.rxbuffer[rb.head.Get()%bufferSize][:], val) 33 return true 34 } 35 return false 36 } 37 38 // Get returns a byte from the buffer. If the buffer is empty, 39 // the method will return a false as the second value. 40 func (rb *RingBuffer) Get() ([]byte, bool) { 41 if rb.Used() != 0 { 42 rb.tail.Set(rb.tail.Get() + 1) 43 return rb.rxbuffer[rb.tail.Get()%bufferSize][:], true 44 } 45 return nil, false 46 } 47 48 // Clear resets the head and tail pointer to zero. 49 func (rb *RingBuffer) Clear() { 50 rb.head.Set(0) 51 rb.tail.Set(0) 52 }