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  }