prog8/compiler/res/prog8lib/buffers.p8
2024-11-28 03:30:32 +01:00

209 lines
4.2 KiB
Lua

; **experimental** buffer data structures, API subject to change!!
%option no_symbol_prefixing, ignore_unused
smallringbuffer {
; -- A ringbuffer (FIFO queue) that occupies 256 bytes in memory.
; You can store and retrieve bytes and words. No guards against over/underflow.
; It's optimized for speed and depends on the byte-wrap-around when doing incs and decs.
ubyte fill = 0
ubyte head = 0
ubyte tail = 255
ubyte[256] buffer
sub init() {
; -- (re)initialize the ringbuffer
head = fill = 0
tail = 255
}
sub size() -> ubyte {
return fill
}
sub free() -> ubyte {
return 255-fill
}
sub isfull() -> bool {
return fill>=254
}
sub isempty() -> bool {
return fill<=1
}
sub put(ubyte value) {
; -- store a byte in the buffer
buffer[head] = value
head++
fill++
}
sub putw(uword value) {
; -- store a word in the buffer
fill += 2
buffer[head] = lsb(value)
head++
buffer[head] = msb(value)
head++
}
sub get() -> ubyte {
; -- retrieves a byte from the buffer
fill--
tail++
return buffer[tail]
}
sub getw() -> uword {
; -- retrieves a word from the buffer
fill -= 2
tail++
cx16.r0L = buffer[tail]
tail++
cx16.r0H = buffer[tail]
return cx16.r0
}
}
; note: for a "small stack" (256 bytes size) just use the CPU stack via sys.push[w] / sys.pop[w].
stack {
; -- A stack (LIFO) that uses a block of 8 KB of memory. Growing downward from the top of the buffer.
; You can store and retrieve bytes and words. There are no guards against stack over/underflow.
uword sp = 8191
uword buffer_ptr = memory("buffers_stack", 8192, 0)
sub init() {
sp = 8191
}
sub size() -> uword {
return 8191-sp
}
sub free() -> uword {
return sp
}
sub isfull() -> bool {
return sp==0
}
sub isempty() -> bool {
return sp==8191
}
sub push(ubyte value) {
; -- put a byte on the stack
buffer_ptr[sp] = value
sp--
}
sub pushw(uword value) {
; -- put a word on the stack (lsb first then msb)
buffer_ptr[sp] = lsb(value)
sp--
buffer_ptr[sp] = msb(value)
sp--
}
sub pop() -> ubyte {
; -- pops a byte off the stack
sp++
return buffer_ptr[sp]
}
sub popw() -> uword {
; -- pops a word off the stack.
sp++
cx16.r0H = buffer_ptr[sp]
sp++
cx16.r0L = buffer_ptr[sp]
return cx16.r0
}
}
ringbuffer {
; -- A ringbuffer (FIFO queue) that uses a block of 8 KB of memory.
; You can store and retrieve bytes and words too. No guards against buffer under/overflow.
uword fill = 0
uword head = 0
uword tail = 8191
uword buffer_ptr = memory("buffers_ringbuffer", 8192, 0)
sub init() {
head = fill = 0
tail = 8191
}
sub size() -> uword {
return fill
}
sub free() -> uword {
return 8191-fill
}
sub isempty() -> bool {
return fill==0
}
sub isfull() -> bool {
return fill>=8191
}
sub put(ubyte value) {
; -- store a byte in the buffer
buffer_ptr[head] = value
inc_head()
fill++
}
sub putw(uword value) {
; -- store a word in the buffer
fill += 2
buffer_ptr[head] = lsb(value)
inc_head()
buffer_ptr[head] = msb(value)
inc_head()
}
sub get() -> ubyte {
; -- retrieves a byte from the buffer
fill--
inc_tail()
return buffer_ptr[tail]
}
sub getw() -> uword {
; -- retrieves a word from the buffer
fill -= 2
inc_tail()
cx16.r0L = buffer_ptr[tail]
inc_tail()
cx16.r0H = buffer_ptr[tail]
return cx16.r0
}
sub inc_head() {
head++
if msb(head)==$20
head=0
}
sub inc_tail() {
tail++
if msb(tail)==$20
tail=0
}
}