;********************************************************************** ;* Filename: mac_fifo.inc ;* Project: EPROM emulator ;* Date: 05 June 2005 ;* Version: 0.1 ;* Author: Philip Pemberton ;* ;* FIFO macros. Based on code by Olin Lathrop / Embed Inc. ;********************************************************************** ; *************************************************************** ; * Copyright (C) 2004, Embed Inc (http://www.embedinc.com) * ; * * ; * Permission to copy this file is granted as long as this * ; * copyright notice is included in its entirety at the * ; * beginning of the file, whether the file is copied in whole * ; * or in part and regardless of whether other information is * ; * added to the copy. * ; * * ; * The contents of this file may be used in any way, * ; * commercial or otherwise. This file is provided "as is", * ; * and Embed Inc makes no claims of suitability for a * ; * particular purpose nor assumes any liability resulting from * ; * its use. * ; *************************************************************** ; ;********************************************************************** ;** MACROS ;********************************************************************** ; ;*********************************************************************** ; ; FIFO (first in, first out) queue handling. ; ; The format of a FIFO in memory is: ; ; name+0 - number of data bytes currently in the queue ; ; name+1 - offset into the queue of where to put the next byte + 1 ; ; name+2 - offset into the queue of where to get the next byte from + 1 ; ; name+3 thru name+2+size - Data buffer. Sequential bytes are written ; and read at decreasing addresses until the start of the buffer is ; reached, in which case the next address wraps back to the end of the ; buffer. ; ; Define symbolic constants for the offset of various special bytes from ; the start of a FIFO. All subsequent code uses these symbols instead ; of assuming the bytes are at fixed offsets. ; fifo_ofs_n equ 0 ;offset from FIFO label for number of bytes in buffer fifo_ofs_put equ 1 ;offset from FIFO label for PUT index fifo_ofs_get equ 2 ;offset from FIFO label for GET index fifo_ofs_buf equ 3 ;offset from FIFO label for start of buffer ; ;******************** ; ; Macro FIFO_DEFINE name size ; ; Define a first in, first out queue. The symbol NAME will be defined as ; the first byte of the queue structure. Size is the maximum number of ; data bytes the queue will be able to hold. ; fifo_define macro name, size name res 1 ;number of data bytes currently in the queue res 1 ;put offset res 1 ;get offset res size ;the data buffer endm ; ;******************** ; ; Macro FIFO_INIT name ; ; Initialize the FIFO at NAME. The register bank must be set for access ; to the FIFO state. ; fifo_init macro name clrf name + fifo_ofs_n ;indicate the FIFO is empty movlw 1 movwf name + fifo_ofs_put ;init PUT index movwf name + fifo_ofs_get ;init GET index endm ; ;******************** ; ; Macro FIFO_SKIP_EMPTY name ; ; Skips the next instruction after the macro if the FIFO at NAME is ; empty. The register bank must be set for access to the FIFO state. ; fifo_skip_empty macro name if fam_16 || fam_12 tstf name + fifo_ofs_n ;set Z if FIFO empty skpz exitm endif if fam_18 tstfsz name + fifo_ofs_n ;skip if FIFO empty exitm endif error "Macro FIFO_SKIP_EMPTY not implemented for this processor" endm ; ;******************** ; ; Macro FIFO_SKIP_NEMPTY name ; ; Skips the next instruction after the macro if the FIFO at NAME ; contains at least one data byte. The register bank must be set for ; access to the FIFO state. ; ; W may be trashed. ; fifo_skip_nempty macro name if fam_16 || fam_12 || fam_18 tstf name + fifo_ofs_n ;set Z if FIFO empty skpnz ;FIFO not empty ? exitm endif error "Macro FIFO_SKIP_NEMPTY not implemented for this processor" endm ; ;******************** ; ; Macro FIFO_SKIP_FULL name size ; ; Skips the next instruction after the macro if the FIFO at NAME is ; completely full. The register bank must be set for access to the ; FIFO state. ; ; W is trashed. ; fifo_skip_full macro name, size movlw size ;get max bytes the FIFO can hold subwf name + fifo_ofs_n, w ;compare to number of bytes currently in FIFO ;; movf name + fifo_ofs_n, w ;; addlw 255 - size + 1 skpc ;FIFO is completely full ? endm ; ;******************** ; ; Macro FIFO_SKIP_NFULL name size ; ; Skips the next instruction after the macro if the FIFO at NAME is ; not completely full. The register bank must be set for access to ; the FIFO state. ; ; W is trashed. ; fifo_skip_nfull macro name, size movlw size ;get max bytes the FIFO can hold subwf name + fifo_ofs_n, w ;compare to number of bytes currently in FIFO ;; movf name + fifo_ofs_n, w ;; addlw 255 - size + 1 skpnc ;FIFO is not completely full ? endm ; ;******************** ; ; Macro FIFO_PUT name size data ; ; Add the byte in DATA as the last byte in the FIFO at NAME. SIZE must ; be the maximum number of bytes the FIFO was defined to hold. The ; register bank must be set for access to the FIFO and DATA. Since the ; FIFO is usually not in global RAM, this means DATA must be either in ; global RAM or in the same register bank as the FIFO. ; ; The FIFO may be trashed if it is already full. This should be checked ; before this macro is called. ; ; Note that if the FIFO could be accessed from the interrupt service ; routine, then interrupts should be temporarily disabled around this ; macro. ; ; The indirect register bank must be set for access to the FIFO. ; ; W and the first FSR are trashed. ; fifo_put macro name, size, data ; ; 12 and 16 family processors. ; if fam_16 || fam_12 movlw name + (fifo_ofs_buf - 1) ;get address for buffer index 0 addwf name + fifo_ofs_put, w ;make address of where to write this new byte movwf FSR ;point to where to write the byte movf data, w ;get the data byte into W movwf INDF ;write the data byte into the buffer incf name + fifo_ofs_n, f ;indicate one more byte now in the FIFO movlw size ;get offset for last byte in buffer decf name + fifo_ofs_put, f ;update buffer index to next byte, set Z on wrap skpnz ;not just decrement past beginning of buffer ? movwf name + fifo_ofs_put ;wrap back to end of buffer exitm endif ; ; 18 family processors. ; if fam_18 lFSR 0, name + (fifo_ofs_buf - 1) ;point to base for PUT offset movf name + fifo_ofs_put, w ;get PUT offset into W movff data, plusw0 ;copy the byte into the data buffer incf name + fifo_ofs_n ;indicate one more byte now in the FIFO movlw size ;get new PUT offset if wrapped to end of FIFO dcfsnz name + fifo_ofs_put ;update the PUT index, skip on not wrap movwf name + fifo_ofs_put ;wrap back to the end of the buffer exitm endif error "Macro FIFO_PUT not implemented for this processor" endm ; ;******************** ; ; Macro FIFO_GET name size data ; ; Get the next byte from the FIFO at NAME into DATA. SIZE must ; be the maximum number of bytes the FIFO was defined to hold. The ; register bank must be set for access to the FIFO and DATA. Since the ; FIFO is usually not in global RAM, this means DATA must be either in ; global RAM or in the same register bank as the FIFO. ; ; The FIFO may be trashed if it is already empty. This should be ; checked before this macro is called. ; ; Note that if the FIFO could be accessed from the interrupt service ; routine, then interrupts should be temporarily disabled around this ; macro. ; ; The indirect register bank must be set for access to the FIFO. ; ; W and the first FSR are trashed. ; fifo_get macro name, size, data ; ; 12 and 16 family processors. ; if fam_16 || fam_12 movlw name + (fifo_ofs_buf - 1) ;get address for buffer index 0 addwf name + fifo_ofs_get, w ;make address of where to read new byte from movwf FSR ;point to where to read the byte from movf INDF, w ;get the data byte movwf data ;pass it back decf name + fifo_ofs_n, f ;indicate one less byte now in the FIFO movlw size ;get offset for last byte in buffer decf name + fifo_ofs_get, f ;update buffer index to next byte, set Z on wrap skpnz ;not just decrement past beginning of buffer ? movwf name + fifo_ofs_get ;wrap back to end of buffer exitm endif ; ; 18 family processors. ; if fam_18 lFSR 0, name + (fifo_ofs_buf - 1) ;point to base for GET offset movf name + fifo_ofs_get, w ;get GET offset into W movff plusw0, data ;copy the byte from the buffer into DATA decf name + fifo_ofs_n ;indicate one less byte now in the FIFO movlw size ;get offset for last byte in buffer dcfsnz name + fifo_ofs_get ;update buffer index, skip on not wrap movwf name + fifo_ofs_get ;wrap back to end of buffer exitm endif error "Macro FIFO_GET not implemented for this processor" endm