Taqoz Reloaded v2.8 - Queues / Stacks using Mini-OOF
I needed several queues to stream longs in and out of a test rig for dsp words. A queue would also seem to be a useful means of passing data between COGs. Here is a BUFFER class to enable that. Data can be read out in fifo (queue), lifo (stack) or array modes. There is a word TEST that demonstrates queue and stack modes of operation. Two methods BUFEMPTY? and BUFFULL? allow you to check buffer status. If data is written to an already full buffer:-
- Used as a queue, only the latest data will be saved
- Used as a stack, the bottom entry(s) will be lost
Don't forget to load Mini-OOF before loading this code:-
--- Buffer class ver 5 in Mini-OOF for Taqoz Reloaded v2.8 Bob Edwards July 2022
--- The buffer data type is long
IFDEF *BUFFERL*
FORGET *BUFFERL*
}
pub *BUFFERL* ." Buffers of type long ver 5 using Mini-OOF" ;
4 := CELLS
--- BUFFER class definition
OBJECT CLASS
4 VARI BUFADRL
4 VARI BUFADRH
4 VARI BUFHEAD
4 VARI BUFTAIL
1 VARI BUFSTATUS
METHOD BUFINIT
METHOD BUFEMPTY?
METHOD BUFEMPTY
METHOD BUFFULL?
METHOD BUF!
METHOD BUF@
METHOD BUFPOP
METHOD BUFADR@
METHOD .BUF
END-CLASS BUFFER
private
--- buffer status
0 := partfull
1 := full
2 := empty
public
--- ensure buffer is circular, dir=1 is top address check, dir=0 bottom address check
pri PTRWRAP ( dir ptr -- ptr' )
IF
DUP THIS BUFADRH @ =
IF
DROP THIS BUFADRL @
THEN
ELSE
DUP THIS BUFADRL @ <
IF
DROP THIS BUFADRH @ CELLS -
THEN
THEN
;
--- are HEAD and TAIL pointers equal?
pri PTR= ( -- flag )
THIS BUFHEAD @
THIS BUFTAIL @ =
;
--- create a buffer, n longs in size, and set it as empty
pri noname ( n -- )
WITH
org@ >R
DUP CELLS * org@ + org --- allocate the buffer storage in data space
R> DUP THIS BUFADRL ! --- save start address of buffer
SWAP CELLS * + THIS BUFADRH ! --- save the top limit address of buffer
THIS BUFEMPTY --- set HEAD and TAIL to ADDRL
ENDWITH
; ANON BUFFER DEFINES BUFINIT
--- return true if the buffer is empty
pri noname ( -- flag )
WITH
THIS BUFSTATUS C@ empty = --- return true if buffer empty
ENDWITH
; ANON BUFFER DEFINES BUFEMPTY?
--- empty the buffer of all data
pri noname ( -- )
WITH
THIS BUFADRL @ DUP --- get the buffer start address
THIS BUFHEAD ! --- initialise the data input pointer
THIS BUFTAIL ! --- initialise the data output pointer
empty THIS BUFSTATUS C! --- set buffer status to empty
ENDWITH
; ANON BUFFER DEFINES BUFEMPTY
--- return true if the buffer is full
pri noname ( -- flag )
WITH
THIS BUFSTATUS C@ full = --- return true if buffer is full
ENDWITH
; ANON BUFFER DEFINES BUFFULL?
--- write a long into the buffer
pri noname ( n -- )
WITH
THIS BUFFULL?
IF THIS BUF@ DROP THEN --- if the buffer is alreay full, make room
THIS BUFHEAD @ CELLS +
1 PTRWRAP
DUP THIS BUFHEAD ! --- increment the buffer head pointer
! --- and write the data n
PTR=
IF full ELSE partfull THEN
THIS BUFSTATUS C! --- and update buffer status
ENDWITH
; ANON BUFFER DEFINES BUF!
--- read a long from the front of the buffer (first in, first out)
pri noname ( -- n )
WITH
THIS BUFEMPTY?
IF
0 --- overreading, just return 0
ELSE
THIS BUFTAIL @ CELLS +
1 PTRWRAP
DUP THIS BUFTAIL ! --- increment the buffer head pointer
@ --- and read the data n
PTR=
IF empty ELSE partfull THEN
THIS BUFSTATUS C! --- and update buffer status
THEN
ENDWITH
; ANON BUFFER DEFINES BUF@
--- read a long from the back of the buffer like a stack ( first in, last out )
pri noname ( -- n )
WITH
THIS BUFEMPTY?
IF
0 --- overreading, just return 0
ELSE
THIS BUFHEAD @ DUP @ SWAP --- read the data n ( n [BUFHEAD] -- )
CELLS - 0 PTRWRAP THIS BUFHEAD ! --- decrement the HEAD pointer
PTR=
IF empty ELSE partfull THEN --- update buffer status
THIS BUFSTATUS C! --- and update buffer status
THEN
ENDWITH
; ANON BUFFER DEFINES BUFPOP
--- returns address of nth element, for use as a normal array
pri noname ( -- adr )
BUFADRL @
; ANON BUFFER DEFINES BUFADR@
pri noname
WITH
CRLF ." BUFADRL = " THIS BUFADRL @ .L
CRLF ." BUFADRH = " THIS BUFADRH @ .L
CRLF ." BUFHEAD = " THIS BUFHEAD @ .L
CRLF ." BUFTAIL = " THIS BUFTAIL @ .L
CRLF ." BUFSTATUS = " THIS BUFSTATUS C@
SWITCH
partfull CASE ." partfull" BREAK
full CASE ." full" BREAK
empty CASE ." empty" BREAK
ENDWITH
; ANON BUFFER DEFINES .BUF
--- end of BUFFER class definition
--- Test of the buffer class
10 := bufsize
BUFFER NEW := MYBUF
pub TEST ( -- )
CRLF CRLF
bufsize MYBUF BUFINIT CRLF ." Buffer initialised " bufsize . ." longs in size (do once only as space is allotted)"
MYBUF BUFEMPTY? CRLF ." BUFEMPTY? returns " .
MYBUF BUFFULL? CRLF ." BUFFULL? returns " .
bufsize 2+ FOR I MYBUF BUF! NEXT CRLF ." Buffer overfilled on purpose"
MYBUF BUFEMPTY? CRLF ." BUFEMPTY? returns " .
MYBUF BUFFULL? CRLF ." BUFFULL? returns " .
CRLF ." Now read all buffer, as a buffer"
bufsize FOR MYBUF BUF@ CRLF . NEXT CRLF ." All buffer read as a buffer - note values 0,1 are lost"
MYBUF BUFEMPTY? CRLF ." BUFEMPTY? returns " .
MYBUF BUFFULL? CRLF ." BUFFULL? returns " .
bufsize FOR I MYBUF BUF! NEXT CRLF ." Buffer filled up again and now read again as a stack"
bufsize FOR MYBUF BUFPOP CRLF . NEXT CRLF ." All buffer read as a stack"
MYBUF BUFEMPTY? CRLF ." BUFEMPTY? returns " .
MYBUF BUFFULL? CRLF ." BUFFULL? returns " .
;

