ESPKit/sources/DSS/buffer.asm

193 lines
3.2 KiB
NASM

; ======================================================
; Circular buffer implementation
; By Roman Boykov. Copyright (c) 2024
; https://github.com/romychs
; ======================================================
IFNDEF _BUFFER
DEFINE _BUFFER
MODULE BUFFER
SIZE_MASK EQU 0x1FFF
; ------------------------------------------------------
; Init circular buffer before use
; Reset pointers and allocate memory
; ------------------------------------------------------
INIT
; reset buffer pointers
LD HL,0x0000
LD (PTR_SET), HL
LD (PTR_GET), HL
DI
IN A,(PAGE_1)
LD (SAVE_P1), A
; request one 16k page
LD B,1
DSS_EXEC DSS_GETMEM
JR C,MAL_ERROR
; save handler
LD (MEMHND),A
; map allocated mem to p1
LD HL,PAGE1_ADDR
LD B,0
LD A,(MEMHND)
DSS_EXEC DSS_SETMEM
JR C,MAL_ERROR
;LD (SAVE_P1),A
RET
MAL_ERROR
LD DE,MSG_MAL_VAL
LD C, A
CALL UTIL.HEXB
MSG_MAL
DB "Memory allocation error: 0x"
MSG_MAL_VAL
DB "xx",0
; ------------------------------------------------------
; Deallocate memory, allocated by INIT. Call this before
; exit to DSS
; ------------------------------------------------------
FREE
; free allocated memory
LD A,(MEMHND)
CP 0xFF
JR Z, NO_MA
DSS_EXEC DSS_FREEMEM
NO_MA
; restore page
LD A,(SAVE_P1)
CP 0xFF
JR Z, NO_PA
OUT (PAGE_1),A
NO_PA
RET
; ------------------------------------------------------
; PUT Data to buffer
; Inp: C - byte to place
; Out: CF=1 if no space
; ------------------------------------------------------
PUT
PUSH HL,DE
LD HL,(PTR_HEAD_P)
LD DE,(PTR_TAIL)
LD A,L
CP E
JP NZ, P_NOTF
LD A, H
CP D
JP NZ, P_NOTF
SCF
JR P_RET
P_NOTF
; put value to buffer
OR D,0x40 ; p1
LD (DE),C
; increment and wrap tail ptr
INC DE
LD A, D
AND 0x1F
LD D, A
LD (PTR_TAIL), DE
P_RET
POP DE,HL
RET
; ------------------------------------------------------
; GET Data from buffer
; Out: CF=1 if empty
; else A - byte from buffer
; ------------------------------------------------------
GET
PUSH HL,DE
LD HL,(PTR_HEAD)
LD DE,(PTR_TAIL)
LD A,L
CP E
JP NZ, G_NOTE
LD A, H
CP D
JP NZ, G_NOTE
SCF
JR G_RET
G_NOTE
; store previous head ptr
LD (PTR_HEAD_P), HL
; get value
LD A,H
OR 0x40
LD H,A
LD C, (HL)
; inc and wrap head ptr
INC HL
LD A, H
AND 0x1F
LD H, A
LD (PTR_HEAD), HL
G_RET
POP DE,HL
RET
; ------------------------------------------------------
; Check buffer is full
; Out: CF=1 if full
; ------------------------------------------------------
IS_FULL
PUSH HL,DE
LD HL,(PTR_HEAD_P)
LD DE,(PTR_TAIL)
SBC HL,DE
JP NZ, ISF_NOTF
SCF
JR ISF_RET
ISF_NOTF
AND A
ISF_RET
POP DE,HL
RET
; ------------------------------------------------------
; Check buffer is empty
; Out: CF=1 if empty
; ------------------------------------------------------
IS_EMPTY
PUSH HL,DE
LD HL,(PTR_HEAD)
LD DE,(PTR_TAIL)
SBC HL,DE
JR NZ, ISF_NOTF
SCF
JR ISF_RET
; buffer set position
PTR_TAIL
DW 0x0000
; buffer get position
PTR_HEAD
DW 0x0000
; buffer previous head position
PTR_HEAD_P
DW 0x0000
; habler for allocated memory
MEMHND
DB 0xFF
; storage for old mem page
SAVE_P1
DB 0xFF
ORG 0x5000
RX_BUFFER
ENDMODULE
ENDIF