; **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 ubyte bank sub init(ubyte rambank) { ; -- initialize the stack, must be called before use. Supply the HiRAM bank to use as buffer space. sp = $bfff bank = rambank } sub size() -> uword { return $bfff-sp } sub free() -> uword { return sp-$a000 } sub isfull() -> bool { return sp<=$a001 } sub isempty() -> bool { return sp==$bfff } sub push(ubyte value) { ; -- put a byte on the stack sys.push(cx16.getrambank()) cx16.rambank(bank) @(sp) = value sp-- cx16.rambank(sys.pop()) } sub pushw(uword value) { ; -- put a word on the stack (lsb first then msb) sys.push(cx16.getrambank()) cx16.rambank(bank) @(sp) = lsb(value) sp-- @(sp) = msb(value) sp-- cx16.rambank(sys.pop()) } sub pop() -> ubyte { ; -- pops a byte off the stack sys.push(cx16.getrambank()) cx16.rambank(bank) sp++ cx16.r0L = @(sp) cx16.rambank(sys.pop()) return cx16.r0L } sub popw() -> uword { ; -- pops a word off the stack. sys.push(cx16.getrambank()) cx16.rambank(bank) sp++ cx16.r0H = @(sp) sp++ cx16.r0L = @(sp) cx16.rambank(sys.pop()) 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, head, tail ubyte bank = 255 ; set via init() sub init(ubyte rambank) { ; -- initialize the ringbuffer, must be called before use. Supply the HiRAM bank to use as buffer space. head = $a000 tail = $bfff fill = 0 bank = rambank } sub size() -> uword { return fill } sub free() -> uword { return $1fff-fill } sub isempty() -> bool { return fill<=1 } sub isfull() -> bool { return fill>=8191 } sub put(ubyte value) { ; -- store a byte in the buffer sys.push(cx16.getrambank()) cx16.rambank(bank) @(head) = value fill++ inc_head() cx16.rambank(sys.pop()) } sub putw(uword value) { ; -- store a word in the buffer sys.push(cx16.getrambank()) cx16.rambank(bank) pokew(head, value) fill += 2 inc_head() inc_head() cx16.rambank(sys.pop()) } sub get() -> ubyte { ; -- retrieves a byte from the buffer sys.push(cx16.getrambank()) cx16.rambank(bank) fill-- inc_tail() cx16.r0L= @(tail) cx16.rambank(sys.pop()) return cx16.r0L } sub getw() -> uword { ; -- retrieves a word from the buffer sys.push(cx16.getrambank()) cx16.rambank(bank) fill -= 2 inc_tail() cx16.r0L = @(tail) inc_tail() cx16.r0H = @(tail) cx16.rambank(sys.pop()) return cx16.r0 } sub inc_head() { head++ if msb(head)==$c0 head=$a000 } sub inc_tail() { tail++ if msb(tail)==$c0 tail=$a000 } }