Here is a scheme similar to what I use (**warning: untested code**). It is a very clean way of doing it. This version requires no restrictions on the length or location of the buffer. You must be sure that the IRP bit is set properly in chips that have one! #define BUFFER_LEN ; can be any length, not just a power of 2 BUFFER RES BUFFER_LEN ; The actual buffer BSTART RES 1 ; Where to fetch next byte BEND RES 1 ; Where to store next byte ; Rather than have a BFULL variable, this code follows the convention that BSTART==BEND means ; that the buffer is empty. This means that the buffer can never be allowed to be completely filled. ; At initialization BSTART and BEND should both be set to the address of the buffer: movlw BUFFER movwf BSTART movwf BEND [interrupt code] ; - point at next available byte of buffer movf BEND,W movwf FSR ; - put the byte in (even if we are oversstuffing!) ; (this is okay because we never fill the buffer and thus ; there is sure to be a spare byte for this) movf BYTE,W movwf INDF ; - compute new insertion pointer, including checking wraparound ; point at the next byte of memory incf BEND,W ; compare to the address just off the buffer xorlw BUFFER+BUFFER_LEN ; if we run off the buffer then skip instruction that resets pointer skpnz ; load a value that the xorlw below will convert to just BUFFER movlw BUFFER^(BUFFER+BUFFER_LEN) ; either undo the first xorlw above, or change the value loaded by ; the movlw to point to the start of the buffer xorlw BUFFER+BUFFER_LEN ;Fix it ; - see if we have overflowed ; compare to extration pointer xorwf BSTART,W ; skip if we didn't skpnz ; this is bad news goto SOS ; - store the updated insertion pointer ; undo the xorwf above xorwf BSTART,W ; store the updated value movwf BEND [mainline code - includes code to check for something in buffer] ; - setup pointer ; get extraction pointer movwf BSTART,W ; remember it movf FSR ; - check for empty buffer ; compare to insertion pointer xorwf BEND,W ; skip if they are not equal skpnz ; the buffer is empty, nothing to do goto BUFFER_IS_EMPTY ; - get the byte from the buffer ; get byte movf INDF,W ;save it movwf TEMP ; - update extraction pointer including checking wraparound ; point at the next byte of memory incf BSTART,W ; compare to the address just off the buffer xorlw BUFFER+BUFFER_LEN ; if we run off the buffer then skip instruction that resets pointer skpnz ; load a value that the xorlw below will conver to just BUFFER movlw BUFFER^(BUFFER+BUFFER_LEN) ; either undo the first xorlw above, or change the value loaded by ; the movlw to point to the start of the buffer xorlw BUFFER+BUFFER_LEN ;Fix it ; save updated buffer pointer movwf BSTART This scheme has some very important characteristics that make it very easy to prove that it is threadsafe: 1: The BSTART variable is only modified by mainline code. 2: The BEND variable is only modified by interrupt code 3: The mainline code only makes one reference to BEND, which means it cannot see an inconsistent state of the buffer. 4: The interrupt code does reference BSTART more than once, but we know the mainline can't change it in between. 5: BEND is only updated after the new byte is safely in the buffer 6: BSTART is only updated after the byte has been safely extracted from the buffer Bob Ammerman RAm Systems -- http://www.piclist.com PIC/SX FAQ & list archive View/change your membership options at http://mailman.mit.edu/mailman/listinfo/piclist