;******************************************************************************** ; @module ringbuffer ; @type utility ; @details ; Size of the ringbuffer is RBUF_MEM_END - RBUF_MEM_START - 2, since two bytes ; are used by the read and write pointer ; The RBUF_NAME variable must be defined, the functions will then be exported ; as rb__ where = init, read or write ; @requires ; RBUF_MEM_START: Start address of ringbuffer memory space ; RBUF_MEM_END: End address of ringbuffer memory space ; RBUF_NAME: Name of the ringbuffer ;******************************************************************************** .ifndef RBUF_MEM_START .fatal "RBUF_MEM_START not defined" .endif .ifndef RBUF_MEM_END .fatal "RBUF_MEM_END not defined" .endif ; can not detect if RBUF_NAME is defined, if it is not you will get ; "String constant expected" Error on the line below .define _RBUF_NAME .concat("rb_", RBUF_NAME) RB_WRITE = RBUF_MEM_START ; write pointer, relative to RB_WRITE RB_READ = RBUF_MEM_START + 1 ; read ponter, relative to RB_START RB_START = RBUF_MEM_START + 2 RB_LENGTH = RBUF_MEM_END - RBUF_MEM_START - 2 .if RB_LENGTH < 1 .fatal "buffer size too small, must be at least 1" .endif .if RB_LENGTH > $ff .fatal "buffer size too large, must be <= $ff" .endif ;******************************************************************************** ; @function Initialize the buffer ;******************************************************************************** .ident(.concat(_RBUF_NAME, "_init")): .scope stz RB_WRITE stz RB_READ rts .endscope ;******************************************************************************** ; @function Read a value from the buffer ; @details ; If there is no value to be read, the Pz will be set ; @returns A: value ; @modifies: A, X ;******************************************************************************** .ident(.concat(_RBUF_NAME, "_read")): .scope ldx RB_READ cpx RB_WRITE beq @rb_read_rts ; if buffer empty lda RB_START,x Inc_buf_ptr RB_READ inx ; increment RB_READ pointer, not using macro bec. of unknown Pz cpx #RB_LENGTH beq @read_wrap stx RB_READ @rb_read_rts: rts @read_wrap: ; ptr == RB_LENGTH -> ptr = 0 stz RB_READ ; make sure Pz is not set ldx #$01 rts .endscope ;******************************************************************************** ; @function Write a value to the buffer ; @param A: value to store ; @modifies: X ;******************************************************************************** ;TODO increment read when write reaches it .ident(.concat(_RBUF_NAME, "_write")): .scope ; lda kp_VALUES, x ; load the char in a ldx RB_WRITE sta RB_START,x inx ; increment write pointer cpx #RB_LENGTH beq @write_wrap stx RB_WRITE @check_buf_full: ; increment read if buffer is full cpx RB_READ beq read_inc rts @write_wrap: ; ptr == RB_LENGTH -> ptr = 0 stz RB_WRITE bra @check_buf_full @read_inc: ldx RB_READ inx cpx #RB_LENGTH beq read_wrap stx RB_READ rts @read_wrap: ; ptr == RB_LENGTH -> ptr = 0 stz RB_READ rts .endscope .undefine _RBUF_NAME .undefine RBUF_NAME