github.com/tinygo-org/tinygo@v0.31.3-0.20240404173401-90b0bf646c27/src/machine/buffer.go (about)

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