diff --git a/firmware/one-chip.asm b/firmware/one-chip.asm index 2713452..9883223 100644 --- a/firmware/one-chip.asm +++ b/firmware/one-chip.asm @@ -8,22 +8,6 @@ ; -;;; License ;;; - -; This program is free software: you can redistribute it and/or modify -; it under the terms of the GNU General Public License as published by -; the Free Software Foundation, either version 3 of the License, or -; (at your option) any later version. -; -; This program is distributed in the hope that it will be useful, -; but WITHOUT ANY WARRANTY; without even the implied warranty of -; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -; GNU General Public License for more details. -; -; You should have received a copy of the GNU General Public License -; along with this program. If not, see . - - ;;; Connections ;;; ;;; ;;; @@ -77,7 +61,13 @@ DNOP macro ;FLAGS: LR_FRM equ 7 ;Set when received frame registers have changed -CTS_PLS equ 6 ;Set when a CTS frame should trigger a send from queue +LR_CROK equ 6 ;Set when CRC of last frame passed +CTS_PLS equ 5 ;Set when a CTS frame should trigger a send from queue +TMPFLAG equ 4 ;Used as temporary storage in transmitter + +;FEATURES: +CALCCRC equ 7 ;Set if transmitter should calculate CRC itself +CHKCRC equ 6 ;Set if receiver should check CRC and signal bad CRCs ;;; Variable Storage ;;; @@ -86,18 +76,18 @@ CTS_PLS equ 6 ;Set when a CTS frame should trigger a send from queue FLAGS ;You've got to have flags LR_BUF ;Receiver buffer + LR_BUF2 ;Receiver buffer + LR_CCRC1 ;Receiver CRC register + LR_CCRC2 ; " LR_STATE ;Receiver state pointer UR_LEN ;Current length of UART receiver queue GBACKOFF ;Global backoff mask LBACKOFF ;Local backoff mask COL_HIST ;Collision history for last 8 transmissions DEF_HIST ;Deferral history for last 8 transmissions - UR_DEST ;First five bytes of frame loaded for transmission - UR_SRC ; " - UR_TYPE ; " - UR_4TH ; " - UR_5TH ; " ATTEMPTS ;Number of attempts at this transmission + FEATURES ;Feature flags + D2 D1 D0 @@ -144,16 +134,19 @@ CTS_PLS equ 6 ;Set when a CTS frame should trigger a send from queue FSR1L_TM ;Temp registers when using FSR1 to modify the node ID INDF1_TM ; bitmap - LT_CRC1 ;Running CRC value calculated by SendByte + LT_CRC1 ;Running CRC value calculated by SendByte/SendFromQueue LT_CRC2 ; " - LT_CRCX ;Temp variable used by SendByte when calculating CRC + LT_CRCX ;Temp variable used when calculating CRC LT_LENH ;Number of bytes to be read from queue by SendFromQueue LT_LENL ; " LT_BUF ;Buffer used to hold the byte being sent over LocalTalk LT_BUF2 ;Temporary buffer LT_ONES ;Count of consecutive ones sent by LT transmitter - LR_CCRC1 ;CRC register used to calculate the CRC of incoming - LR_CCRC2 ; control frames + UR_DEST ;First five bytes of frame loaded for transmission + UR_SRC ; " + UR_TYPE ; " + UR_4TH ; " + UR_5TH ; " endc @@ -262,8 +255,30 @@ Init movlw B'11001000' movwf INTCON + clrf FEATURES ;All optional features off to start + clrf LR_CCRC1 ;Receiver CRC registers cleared to ones to + decf LR_CCRC1,F ; start, we don't have time to do this when we + clrf LR_CCRC2 ; jump into the code + decf LR_CCRC2,F + bra PrepForNextFrame +;entered with BSR = 2 +AwaitFeatures + call CheckLtReceiver ;Check for and deal with receiver activity + movf UR_LEN,W ;If there isn't yet a byte in the UART receiver + addlw -1 ; queue, loop around again + btfss STATUS,C ; " + bra AwaitFeatures ; " + movwf UR_LEN ;Decrement the UART receiver queue size by 1 + movlw B'11111011' ;If the pop off the queue dropped the length + btfss UR_LEN,6 ; below 64, assert CTS so the host sends us + andwf LATA,F ; data again + moviw FSR1++ ;Pop the next byte off the UART receiver queue + bcf FSR1L,7 ; " + movwf FEATURES ;Store this byte into the features bitmap + bra AwaitCommand ;Return to await next command + ;entered with BSR = 2 AwaitNodeId call CheckLtReceiver ;Check for and deal with receiver activity @@ -393,6 +408,9 @@ AwaitCommand addlw -1 ;If it's two, that's the command byte for btfsc STATUS,Z ; setting the node ID bitmap, so go wait for bra AwaitNodeId ; that data + addlw -1 ;If it's three, that's the command byte for + btfsc STATUS,Z ; setting the features bitmap, so go wait for + bra AwaitFeatures ; that data bra AwaitCommand ;All other commands are considered no-ops ;entered with BSR = ? @@ -442,7 +460,7 @@ PrepForNextFrame btfsc WREG,7 ; " clrf DEF_HIST ; " btfsc WREG,7 ; " - decf DEF_HIST ; " + decf DEF_HIST,F ; " lslf COL_HIST,F ;Progress the collision and deferral history lslf DEF_HIST,F ; logs to make space for what happens this time movf GBACKOFF,W ;Copy the global backoff mask into the local @@ -545,9 +563,10 @@ WaitToSendCtrl WTSC1 bcf INTCON,GIE ;Disable interrupts before checking Timer2 btfss PIR1,TMR2IF ;Unless Timer2 has interrupted, loop around bra WaitToSendCtrl ; again - btfss UR_TYPE,7 ;If the loaded frame is a control frame, just - bra WTSC2 ; go ahead and send it and then prepare for the - call SendControlFrame; next frame + movlb 2 ;If the loaded frame is a control frame, just + btfss UR_TYPE,7 ; go ahead and send it and then prepare for the + bra WTSC2 ; next frame + call SendControlFrame; " bra PrepForNextFrame; " WTSC2 call SendRts ;If it's a data frame, send an RTS frame first movlb 0 ;Set Timer2 to interrupt after 200us, the @@ -556,21 +575,23 @@ WTSC2 call SendRts ;If it's a data frame, send an RTS frame first bsf T2CON,TMR2ON ;Activate Timer2 clrf TMR2 ;Reset Timer2 bcf PIR1,TMR2IF ;Clear the Timer2 interrupt flag - incf UR_DEST,W ;If frame's destination is broadcast (0xFF) - btfsc STATUS,Z ; then we want to wait for 200us of silence - bra WaitForSilence ; before sending; otherwise we want to wait for - bra WaitForCts ; a CTS frame and 200us is our timeout + movlb 2 ;If frame's destination is broadcast (0xFF) + incf UR_DEST,W ; then we want to wait for 200us of silence + movlb 0 ; before sending; otherwise we want to wait for + btfsc STATUS,Z ; a CTS frame and 200us is our timeout + bra WaitForSilence ; " + bra WaitForCts ; " ;entered with BSR = ? GiveUp + movlb 2 btfsc UR_TYPE,7 ;If loaded frame is a control frame, we already bra PrepForNextFrame; have it in full - movlb 2 ;If loaded frame is a data frame, we need to - movf UR_4TH,W ; extract the length from the 4th and 5th bytes - andlw B'00000011' ; and drain that many characters from the UART - movwf LT_LENH ; receiver queue (even if it doesn't already - movf UR_5TH,W ; contain all of them) - movwf LT_LENL ; " + movf UR_4TH,W ;If loaded frame is a data frame, we need to + andlw B'00000011' ; extract the length from the 4th and 5th bytes + movwf LT_LENH ; and drain that many characters from the UART + movf UR_5TH,W ; receiver queue (even if it doesn't already + movwf LT_LENL ; contain all of them) GiveUp1 movlw -1 ;Decrement the length counter; if it was addwf LT_LENL,F ; already zero, we're done addwfc LT_LENH,F ; " @@ -663,6 +684,8 @@ DealWithFrame btfss FLAGS,LR_FRM ;If the incoming frame regs haven't changed, return ; we have nothing to do here bcf FLAGS,LR_FRM ;This is so we know if regs changed under us + btfss FLAGS,LR_CROK ;If the frame's CRC check failed, the frame is + return ; invalid, ignore it btfss LR_TYPE,7 ;If the frame is not a control frame, there's return ; nothing to do; host handles data frames movf FSR1L,W ;Using the node ID bitmap, check whether this @@ -687,55 +710,6 @@ DealWithFrame movf INDF1_TM,F ; " btfsc STATUS,Z ; " return ; " - clrf LR_CCRC1 ;Clear the CRC check registers to all ones so - clrf LR_CCRC2 ; we can start checking the CRC of the frame - decf LR_CCRC1,F ; " - decf LR_CCRC2,F ; " - movf LR_DEST,W ;Update the CRC check registers with the frame - xorwf LR_CCRC1,W ; destination - movwf LR_CCRC1 ; " - movlp high CrcLut1 ; " - callw ; " - xorwf LR_CCRC2,W ; " - xorwf LR_CCRC1,F ; " - xorwf LR_CCRC1,W ; " - xorwf LR_CCRC1,F ; " - movlp high CrcLut2 ; " - callw ; " - movwf LR_CCRC2 ; " - movf LR_SRC,W ;Update the CRC check registers with the frame - xorwf LR_CCRC1,W ; source - movwf LR_CCRC1 ; " - movlp high CrcLut1 ; " - callw ; " - xorwf LR_CCRC2,W ; " - xorwf LR_CCRC1,F ; " - xorwf LR_CCRC1,W ; " - xorwf LR_CCRC1,F ; " - movlp high CrcLut2 ; " - callw ; " - movwf LR_CCRC2 ; " - movf LR_TYPE,W ;Update the CRC check registers with the frame - xorwf LR_CCRC1,W ; type - movwf LR_CCRC1 ; " - movlp high CrcLut1 ; " - callw ; " - xorwf LR_CCRC2,W ; " - xorwf LR_CCRC1,F ; " - xorwf LR_CCRC1,W ; " - xorwf LR_CCRC1,F ; " - movlp high CrcLut2 ; " - callw ; " - movwf LR_CCRC2 ; " - movlp 0 ; " - comf LR_CCRC1,W ;If the calculated CRC does not match the - xorwf LR_CRC1,W ; received one, the frame is invalid and we're - btfss STATUS,Z ; done - return ; " - comf LR_CCRC2,W ; " - xorwf LR_CRC2,W ; " - btfss STATUS,Z ; " - return ; " bcf INTCON,GIE ;Disable interrupts so frame vars don't change btfsc FLAGS,LR_FRM ;If this flag is set, regs changed under us so bra DealWiR ; we can't act, reenable interrupts and return @@ -784,13 +758,16 @@ SendControlFrame DNOP ;30-31 call SendByte ;32-25 movf UR_4TH,W ;26 - movwf LT_BUF ;27 - DNOP ;28-29 - DNOP ;30-31 + btfsc FEATURES,CALCCRC;27 + comf LT_CRC1,W ;28 + movwf LT_BUF ;29 + comf LT_CRC2,W ;30 + movwf LT_BUF2 ;31 call SendByte ;32-25 movf UR_5TH,W ;26 - movwf LT_BUF ;27 - DNOP ;28-29 + btfsc FEATURES,CALCCRC;27 + movf LT_BUF2,W ;28 + movwf LT_BUF ;29 DNOP ;30-31 call SendByte ;32-25 DNOP ;26-27 @@ -819,24 +796,31 @@ SendDataFrame call SendByte ;32-25 movf UR_TYPE,W ;26 movwf LT_BUF ;27 - DNOP ;28-29 - DNOP ;30-31 + nop ;28 + bsf FLAGS,TMPFLAG ;29 If frame length is 2, we need to overwrite + btfss FEATURES,CALCCRC;30 the CRC bytes with our calculated CRC; if + bcf FLAGS,TMPFLAG ;31 the feature is off, never do this call SendByte ;32-25 movf UR_4TH,W ;26 movwf LT_BUF ;27 andlw B'00000011' ;28 movwf LT_LENH ;29 - DNOP ;30-31 + btfss STATUS,Z ;30 If high byte of length is not zero, length + bcf FLAGS,TMPFLAG ;31 of frame is not 2 call SendByte ;32-25 movf UR_5TH,W ;26 movwf LT_BUF ;27 movwf LT_LENL ;28 - nop ;29 - DNOP ;30-31 + xorlw 2 ;29 If low byte of length is not 2, length of + btfss STATUS,Z ;30 frame is not 2 + bcf FLAGS,TMPFLAG ;31 " call SendByte ;32-25 - DNOP ;26-27 - DNOP ;28-29 - DNOP ;30-31 + comf LT_CRC1,W ;26 If length of frame is 2, overstrike the + btfsc FLAGS,TMPFLAG ;27 first byte to send with the first byte of + movwf INDF1 ;28 the CRC and store the second for later + comf LT_CRC2,W ;29 use; this takes care of the fact that we + btfsc FLAGS,TMPFLAG ;30 won't have time to do it later + movwf LT_BUF2 ;31 " call SendFromQueue ;32-25 (Branches into SendPostamble) movlb 7 ;Clear the inevitable IOC interrupt that came bcf IOCAF,IOCAF5 ; in while (and because) we were transmitting @@ -1184,8 +1168,13 @@ SendFrL movlw B'00100000' ;34 Load pattern for inverting LocalTalk pin bsf LT_ONES,0 ;21 " btfsc LT_ONES,5 ;22 If the consecutive ones counter has reached call SendByteStuff ;23(-24) five, stuff a zero - DELAY 3 ;24-32 - nop ;33 + movf INDF1,W ;24 Update LT_CRC1 with the byte being sent; + xorwf LT_CRC1,W ;25 note that we don't movlp back to 0 because + movwf LT_CRCX ;26 we don't have time; this only works + movlp high CrcLut1 ;27 because CrcLut1 is below the page boundary + callw ;28-31 " + xorwf LT_CRC2,W ;32 " + movwf LT_CRC1 ;33 " movlw B'00100000' ;34 Load pattern for inverting LocalTalk pin xorwf LATA,F ;00 Invert LocalTalk pin for clock call SendDoUartSvc ;01-02 (03-14) Service the UART receiver @@ -1198,8 +1187,12 @@ SendFrL movlw B'00100000' ;34 Load pattern for inverting LocalTalk pin bsf LT_ONES,0 ;21 " btfsc LT_ONES,5 ;22 If the consecutive ones counter has reached call SendByteStuff ;23(-24) five, stuff a zero - DELAY 3 ;24-32 - nop ;33 + movf LT_CRCX,W ;24 Update LT_CRC2 with the byte being sent + movlp high CrcLut2 ;25 " + callw ;26-29 " + movlp 0 ;30 " + movwf LT_CRC2 ;31 " + DNOP ;32-33 movlw B'00100000' ;34 Load pattern for inverting LocalTalk pin xorwf LATA,F ;00 Invert LocalTalk pin for clock call SendDoUartSvc ;01-02 (03-14) Service the UART receiver @@ -1212,8 +1205,16 @@ SendFrL movlw B'00100000' ;34 Load pattern for inverting LocalTalk pin bsf LT_ONES,0 ;21 " btfsc LT_ONES,5 ;22 If the consecutive ones counter has reached call SendByteStuff ;23(-24) five, stuff a zero - DELAY 3 ;24-32 - nop ;33 + bsf FLAGS,TMPFLAG ;24 If frame length is 2, we need to overwrite + btfss FEATURES,CALCCRC;25 the CRC bytes with our calculated CRC; if + bcf FLAGS,TMPFLAG ;26 the feature is off, never do this + movf LT_LENH,W ;27 If the upper byte of the remaining byte + btfss STATUS,Z ;28 counter is not zero, remaining byte + bcf FLAGS,TMPFLAG ;29 counter is not 2 + movf LT_LENL,W ;30 If the lower byte of the remaining byte + xorlw 2 ;31 counter is not 2, remaining byte counter + btfss STATUS,Z ;32 is not 2; we will use this flag later + bcf FLAGS,TMPFLAG ;33 " movlw B'00100000' ;34 Load pattern for inverting LocalTalk pin xorwf LATA,F ;00 Invert LocalTalk pin for clock call SendDoUartSvc ;01-02 (03-14) Service the UART receiver @@ -1226,8 +1227,16 @@ SendFrL movlw B'00100000' ;34 Load pattern for inverting LocalTalk pin bsf LT_ONES,0 ;21 " btfsc LT_ONES,5 ;22 If the consecutive ones counter has reached call SendByteStuff ;23(-24) five, stuff a zero - DELAY 3 ;24-32 - nop ;33 + moviw FSR1++ ;24 Advance the receiver queue pop pointer + bcf FSR1L,7 ;25 " + comf LT_CRC1,W ;26 If the remaining byte counter is at 2, set + btfsc FLAGS,TMPFLAG ;27 the next byte to be sent to the first byte + movwf INDF1 ;28 of the CRC and store the second byte of + comf LT_CRC2,W ;29 the CRC to be sent later (when the + btfsc FLAGS,TMPFLAG ;30 remaining byte counter is at 1) + movwf LT_BUF2 ;31 " + decf FSR1L,F ;32 Regress the receiver queue pop pointer + bcf FSR1L,7 ;33 " movlw B'00100000' ;34 Load pattern for inverting LocalTalk pin xorwf LATA,F ;00 Invert LocalTalk pin for clock call SendDoUartSvc ;01-02 (03-14) Service the UART receiver @@ -1240,8 +1249,16 @@ SendFrL movlw B'00100000' ;34 Load pattern for inverting LocalTalk pin bsf LT_ONES,0 ;21 " btfsc LT_ONES,5 ;22 If the consecutive ones counter has reached call SendByteStuff ;23(-24) five, stuff a zero - DELAY 3 ;24-32 - nop ;33 + bsf FLAGS,TMPFLAG ;24 If frame length is 2, we need to overwrite + btfss FEATURES,CALCCRC;25 the CRC bytes with our calculated CRC; if + bcf FLAGS,TMPFLAG ;26 the feature is off, never do this + movf LT_LENH,W ;27 If the upper byte of the remaining byte + btfss STATUS,Z ;28 counter is not zero, remaining byte + bcf FLAGS,TMPFLAG ;29 counter is not 1 + movf LT_LENL,W ;30 If the lower byte of the remaining byte + xorlw 1 ;31 counter is not 1, remaining byte counter + btfss STATUS,Z ;32 is not 1; we will use this flag later + bcf FLAGS,TMPFLAG ;33 " movlw B'00100000' ;34 Load pattern for inverting LocalTalk pin xorwf LATA,F ;00 Invert LocalTalk pin for clock call SendDoUartSvc ;01-02 (03-14) Service the UART receiver @@ -1254,7 +1271,14 @@ SendFrL movlw B'00100000' ;34 Load pattern for inverting LocalTalk pin bsf LT_ONES,0 ;21 " btfsc LT_ONES,5 ;22 If the consecutive ones counter has reached call SendByteStuff ;23(-24) five, stuff a zero - DELAY 3 ;24-32 + moviw FSR1++ ;24 Advance the receiver queue pop pointer + bcf FSR1L,7 ;25 " + movf LT_BUF2,W ;26 If the remaining byte counter is at 1, set + btfsc FLAGS,TMPFLAG ;27 the next byte to be sent to the second + movwf INDF1 ;28 byte of the CRC that we saved earlier + decf FSR1L,F ;29 Regress the receiver queue pop pointer + bcf FSR1L,7 ;30 " + DNOP ;31-32 nop ;33 movlw B'00100000' ;34 Load pattern for inverting LocalTalk pin xorwf LATA,F ;00 Invert LocalTalk pin for clock @@ -1375,7 +1399,7 @@ SendDoUartCts ;;; CRC Lookup Tables ;;; - org 0x700 + org 0x600 CrcLut1 dt 0x00,0x89,0x12,0x9B,0x24,0xAD,0x36,0xBF @@ -1412,7 +1436,7 @@ CrcLut1 dt 0xC7,0x4E,0xD5,0x5C,0xE3,0x6A,0xF1,0x78 - org 0x800 + org 0x700 CrcLut2 dt 0x00,0x11,0x23,0x32,0x46,0x57,0x65,0x74 @@ -1459,7 +1483,7 @@ CrcLut2 ; \________________/ ; Time period when we should be checking for a clock-inversion - org 0x900 + org 0x800 OutNothingSkip movlw B'00001111' ;16 If the UART receiver queue length >= 64, @@ -1607,6 +1631,33 @@ InCheckInv bra InReceive ;43 " bra InLostClock ;By this point, we must assume we've lost clock +InSecond + movf LR_BUF2,W ;12 Update the CRC with the last byte received + xorwf LR_CCRC1,W ;13 " + movlp high CrcLut1 ;14 " + callw ;15-18 " + movwf D0 ;19 " + bra InCheckInv ;20-21 + +InFourth + movf LR_BUF2,W ;12 Update the CRC with the last byte received + movwi FSR1++ ;13 " + xorwf LR_CCRC1,W ;14 " + movwf D1 ;15 " + movf D0,W ;16 " + xorwf LR_CCRC2,W ;17 " + movwf LR_CCRC1 ;18 " + nop ;19 + bra InCheckInv ;20-21 + +InSixth + movf D1,W ;12 Update the CRC with the last byte received + movlp high CrcLut2 ;13 " + callw ;14-17 " + movwf LR_CCRC2 ;18 " + nop ;19 + bra InCheckInv ;20-21 + OutReceive bcf IOCAF,IOCAF5 ;00 Ready to detect inversion movlp high OutFSA ;01 Point PCLATH to the out-of-frame FSA for 0 @@ -1632,19 +1683,80 @@ InReceive movwf PCL ;05-06 " InFlag - movlb 3 ;12 Transmit a zero, which is an escape - clrf TXREG ;13 character - movlw 0xFD ;14 Transmit 0xFD, which signifies 'Frame Done' - movwf TXREG ;15 " - movlb 7 ;16 " - bsf FLAGS,LR_FRM ;17 Raise the flag that frame regs have changed - DNOP ;18-19 - bra OutCheckInv ;20-21 Switch to out-of-frame inversion check + bsf FLAGS,LR_CROK ;12 If the whole frame and a correct CRC have + movf LR_CCRC1,W ;13 been fed through the CRC calculator, the + xorlw 0xB8 ;14 registers should be 0xB8 and 0xF0; set + btfss STATUS,Z ;15 flag if this is the case and clear it + bcf FLAGS,LR_CROK ;16 otherwise + movf LR_CCRC2,W ;17 " + xorlw 0xF0 ;18 " + btfss STATUS,Z ;19 " + bcf FLAGS,LR_CROK ;20 " + movlw 0xFC ;21 Compute the correct status to send - if the + btfss FLAGS,LR_CROK ;22 CRC is wrong and CRC checking is enabled, + btfss FEATURES,CHKCRC ;23 this should be 0xFC (frame check failed), + movlw 0xFD ;24 otherwise it should be 0xFD (frame done) + movlb 3 ;25 Transmit a zero, which is an escape + clrf TXREG ;26 character + movwf TXREG ;27 Send the byte computed above + movlb 7 ;28 " + bsf FLAGS,LR_FRM ;29 Raise the flag that frame regs have changed +InFlag2 bcf IOCAF,IOCAF5 ;Ready to detect inversion + movlb 0 ;00 Check if there is a byte waiting from the + bcf STATUS,C ;01 UART + btfsc PIR1,RCIF ;02 " + bsf STATUS,C ;03 " + movlb 3 ;04 If there is a byte waiting from the UART, + btfsc STATUS,C ;05 push it onto the queue + movf RCREG,W ;06 " + movlb 0 ;07 " + btfsc STATUS,C ;08 " + movwi FSR0++ ;09 " + bcf FSR0L,7 ;10 Wrap the queue around + btfsc STATUS,C ;11 If there was a byte waiting from the UART, + incf UR_LEN,F ;12 increment the queue length + movlw B'00001111' ;13 If the UART receiver queue length >= 64, + btfsc UR_LEN,6 ;14 deassert CTS so the host stops sending us + movwf PORTA ;15 data + bcf STATUS,C ;16 Check if there is a byte waiting from the + btfsc PIR1,RCIF ;17 UART + bsf STATUS,C ;18 " + movlb 3 ;19 If there is a byte waiting from the UART, + btfsc STATUS,C ;20 push it onto the queue + movf RCREG,W ;21 " + movlb 0 ;22 " + btfsc STATUS,C ;23 " + movwi FSR0++ ;24 " + bcf FSR0L,7 ;25 Wrap the queue around + btfsc STATUS,C ;26 If there was a byte waiting from the UART, + incf UR_LEN,F ;27 increment the queue length + movlw B'00001111' ;28 If the UART receiver queue length >= 64, + btfsc UR_LEN,6 ;29 deassert CTS so the host stops sending us + movwf PORTA ;30 data + bcf STATUS,C ;31 Check if there is a byte waiting from the + btfsc PIR1,RCIF ;32 UART + bsf STATUS,C ;33 " + movlb 3 ;34 If there is a byte waiting from the UART, + btfsc STATUS,C ;35 push it onto the queue + movf RCREG,W ;36 " + movlb 0 ;37 " + btfsc STATUS,C ;38 " + movwi FSR0++ ;39 " + bcf FSR0L,7 ;40 Wrap the queue around + btfsc STATUS,C ;41 If there was a byte waiting from the UART, + incf UR_LEN,F ;42 increment the queue length + movlw B'00001111' ;43 If the UART receiver queue length >= 64, + btfsc UR_LEN,6 ;44 deassert CTS so the host stops sending us + movwf PORTA ;45 data + movlb 7 ;If there's been an inversion in the elapsed + btfsc IOCAF,IOCAF5 ; ~1.25 bit times, the line is not yet idle and + bra InFlag2 ; we should try again + bra FinishUp ;Else, proceed to finish the receive EmpByte InByte - movf LR_BUF,W ;12 Save the received byte into the frame regs - movwi FSR1++ ;13 using FSR1 + movf LR_BUF,W ;12 Save received byte into second buffer so it + movwf LR_BUF2 ;13 can be CRC'd and copied into the frame regs btfss STATUS,Z ;14 If the received byte is not a zero, just bra InByte2 ;15(-16) transmit it as-is movlb 3 ;16 If the received byte is a zero, transmit @@ -1714,7 +1826,22 @@ InFErr clrf TXREG ; " movlw 0xFE ;Transmit 0xFE, which signifies 'Frame Error' movwf TXREG ; " - bra FinishUp + ;fall through + +OutLostClock +EmpLostClock +FinishUp + movlb 0 ;Deactivate Timer2 and clear its interrupt flag + bcf T2CON,TMR2ON ; so anything that was waiting for it knows + bcf PIR1,TMR2IF ; that a receive event happened while waiting + clrf LR_CCRC1 ;Clear receiver CRC registers to ones since we + decf LR_CCRC1,F ; don't have time to do this when we jump into + clrf LR_CCRC2 ; the receiver + decf LR_CCRC2,F ; " + movf FSR0L,W ;Store the changed UART receiver push point + movlb 31 ; back in its shadow register so it stays the + movwf FSR0L_SHAD ; same when we return from interrupt + retfie InLostClock movlb 0 ;Wait until the UART transmitter is ready for @@ -1730,17 +1857,6 @@ InLostClock movwf TXREG ; " bra FinishUp -OutLostClock -EmpLostClock -FinishUp - movlb 0 ;Deactivate Timer2 and clear its interrupt flag - bcf T2CON,TMR2ON ; so anything that was waiting for it knows - bcf PIR1,TMR2IF ; that a receive event happened while waiting - movf FSR0L,W ;Store the changed UART receiver push point - movlb 31 ; back in its shadow register so it stays the - movwf FSR0L_SHAD ; same when we return from interrupt - retfie - ;;; LocalTalk Receiver State Machines ;;; @@ -2569,7 +2685,7 @@ Is0c0r0 bcf LR_BUF,0 ;07 Is0c1r0 bcf LR_BUF,1 ;07 movlw low Is0c2r0 ;08 movwf LR_STATE ;09 - goto InNothing ;10-11 + goto InSecond ;10-11 Is0c2r0 bcf LR_BUF,2 ;07 movlw low Is0c3r0 ;08 movwf LR_STATE ;09 @@ -2577,7 +2693,7 @@ Is0c2r0 bcf LR_BUF,2 ;07 Is0c3r0 bcf LR_BUF,3 ;07 movlw low Is0c4r0 ;08 movwf LR_STATE ;09 - goto InNothing ;10-11 + goto InFourth ;10-11 Is0c4r0 bcf LR_BUF,4 ;07 movlw low Is0c5r0 ;08 movwf LR_STATE ;09 @@ -2585,7 +2701,7 @@ Is0c4r0 bcf LR_BUF,4 ;07 Is0c5r0 bcf LR_BUF,5 ;07 movlw low Is0c6r0 ;08 movwf LR_STATE ;09 - goto InNothing ;10-11 + goto InSixth ;10-11 Is0c6r0 bcf LR_BUF,6 ;07 movlw low Is0c7r0 ;08 movwf LR_STATE ;09 @@ -2601,7 +2717,7 @@ Is1c0r0 bcf LR_BUF,0 ;07 Is1c1r0 bcf LR_BUF,1 ;07 movlw low Is0c2r0 ;08 movwf LR_STATE ;09 - goto InNothing ;10-11 + goto InSecond ;10-11 Is1c2r0 bcf LR_BUF,2 ;07 movlw low Is0c3r0 ;08 movwf LR_STATE ;09 @@ -2609,7 +2725,7 @@ Is1c2r0 bcf LR_BUF,2 ;07 Is1c3r0 bcf LR_BUF,3 ;07 movlw low Is0c4r0 ;08 movwf LR_STATE ;09 - goto InNothing ;10-11 + goto InFourth ;10-11 Is1c4r0 bcf LR_BUF,4 ;07 movlw low Is0c5r0 ;08 movwf LR_STATE ;09 @@ -2617,7 +2733,7 @@ Is1c4r0 bcf LR_BUF,4 ;07 Is1c5r0 bcf LR_BUF,5 ;07 movlw low Is0c6r0 ;08 movwf LR_STATE ;09 - goto InNothing ;10-11 + goto InSixth ;10-11 Is1c6r0 bcf LR_BUF,6 ;07 movlw low Is0c7r0 ;08 movwf LR_STATE ;09 @@ -2633,7 +2749,7 @@ Is2c0r0 bcf LR_BUF,0 ;07 Is2c1r0 bcf LR_BUF,1 ;07 movlw low Is0c2r0 ;08 movwf LR_STATE ;09 - goto InNothing ;10-11 + goto InSecond ;10-11 Is2c2r0 bcf LR_BUF,2 ;07 movlw low Is0c3r0 ;08 movwf LR_STATE ;09 @@ -2641,7 +2757,7 @@ Is2c2r0 bcf LR_BUF,2 ;07 Is2c3r0 bcf LR_BUF,3 ;07 movlw low Is0c4r0 ;08 movwf LR_STATE ;09 - goto InNothing ;10-11 + goto InFourth ;10-11 Is2c4r0 bcf LR_BUF,4 ;07 movlw low Is0c5r0 ;08 movwf LR_STATE ;09 @@ -2649,7 +2765,7 @@ Is2c4r0 bcf LR_BUF,4 ;07 Is2c5r0 bcf LR_BUF,5 ;07 movlw low Is0c6r0 ;08 movwf LR_STATE ;09 - goto InNothing ;10-11 + goto InSixth ;10-11 Is2c6r0 bcf LR_BUF,6 ;07 movlw low Is0c7r0 ;08 movwf LR_STATE ;09 @@ -2665,7 +2781,7 @@ Is3c0r0 bcf LR_BUF,0 ;07 Is3c1r0 bcf LR_BUF,1 ;07 movlw low Is0c2r0 ;08 movwf LR_STATE ;09 - goto InNothing ;10-11 + goto InSecond ;10-11 Is3c2r0 bcf LR_BUF,2 ;07 movlw low Is0c3r0 ;08 movwf LR_STATE ;09 @@ -2673,7 +2789,7 @@ Is3c2r0 bcf LR_BUF,2 ;07 Is3c3r0 bcf LR_BUF,3 ;07 movlw low Is0c4r0 ;08 movwf LR_STATE ;09 - goto InNothing ;10-11 + goto InFourth ;10-11 Is3c4r0 bcf LR_BUF,4 ;07 movlw low Is0c5r0 ;08 movwf LR_STATE ;09 @@ -2681,7 +2797,7 @@ Is3c4r0 bcf LR_BUF,4 ;07 Is3c5r0 bcf LR_BUF,5 ;07 movlw low Is0c6r0 ;08 movwf LR_STATE ;09 - goto InNothing ;10-11 + goto InSixth ;10-11 Is3c6r0 bcf LR_BUF,6 ;07 movlw low Is0c7r0 ;08 movwf LR_STATE ;09 @@ -2697,7 +2813,7 @@ Is4c0r0 bcf LR_BUF,0 ;07 Is4c1r0 bcf LR_BUF,1 ;07 movlw low Is0c2r0 ;08 movwf LR_STATE ;09 - goto InNothing ;10-11 + goto InSecond ;10-11 Is4c2r0 bcf LR_BUF,2 ;07 movlw low Is0c3r0 ;08 movwf LR_STATE ;09 @@ -2705,7 +2821,7 @@ Is4c2r0 bcf LR_BUF,2 ;07 Is4c3r0 bcf LR_BUF,3 ;07 movlw low Is0c4r0 ;08 movwf LR_STATE ;09 - goto InNothing ;10-11 + goto InFourth ;10-11 Is4c4r0 bcf LR_BUF,4 ;07 movlw low Is0c5r0 ;08 movwf LR_STATE ;09 @@ -2713,7 +2829,7 @@ Is4c4r0 bcf LR_BUF,4 ;07 Is4c5r0 bcf LR_BUF,5 ;07 movlw low Is0c6r0 ;08 movwf LR_STATE ;09 - goto InNothing ;10-11 + goto InSixth ;10-11 Is4c6r0 bcf LR_BUF,6 ;07 movlw low Is0c7r0 ;08 movwf LR_STATE ;09 @@ -2772,7 +2888,7 @@ Is0c0r1 bsf LR_BUF,0 ;07 Is0c1r1 bsf LR_BUF,1 ;07 movlw low Is1c2r1 ;08 movwf LR_STATE ;09 - goto InNothing ;10-11 + goto InSecond ;10-11 Is0c2r1 bsf LR_BUF,2 ;07 movlw low Is1c3r1 ;08 movwf LR_STATE ;09 @@ -2780,7 +2896,7 @@ Is0c2r1 bsf LR_BUF,2 ;07 Is0c3r1 bsf LR_BUF,3 ;07 movlw low Is1c4r1 ;08 movwf LR_STATE ;09 - goto InNothing ;10-11 + goto InFourth ;10-11 Is0c4r1 bsf LR_BUF,4 ;07 movlw low Is1c5r1 ;08 movwf LR_STATE ;09 @@ -2788,7 +2904,7 @@ Is0c4r1 bsf LR_BUF,4 ;07 Is0c5r1 bsf LR_BUF,5 ;07 movlw low Is1c6r1 ;08 movwf LR_STATE ;09 - goto InNothing ;10-11 + goto InSixth ;10-11 Is0c6r1 bsf LR_BUF,6 ;07 movlw low Is1c7r1 ;08 movwf LR_STATE ;09 @@ -2804,7 +2920,7 @@ Is1c0r1 bsf LR_BUF,0 ;07 Is1c1r1 bsf LR_BUF,1 ;07 movlw low Is2c2r1 ;08 movwf LR_STATE ;09 - goto InNothing ;10-11 + goto InSecond ;10-11 Is1c2r1 bsf LR_BUF,2 ;07 movlw low Is2c3r1 ;08 movwf LR_STATE ;09 @@ -2812,7 +2928,7 @@ Is1c2r1 bsf LR_BUF,2 ;07 Is1c3r1 bsf LR_BUF,3 ;07 movlw low Is2c4r1 ;08 movwf LR_STATE ;09 - goto InNothing ;10-11 + goto InFourth ;10-11 Is1c4r1 bsf LR_BUF,4 ;07 movlw low Is2c5r1 ;08 movwf LR_STATE ;09 @@ -2820,7 +2936,7 @@ Is1c4r1 bsf LR_BUF,4 ;07 Is1c5r1 bsf LR_BUF,5 ;07 movlw low Is2c6r1 ;08 movwf LR_STATE ;09 - goto InNothing ;10-11 + goto InSixth ;10-11 Is1c6r1 bsf LR_BUF,6 ;07 movlw low Is2c7r1 ;08 movwf LR_STATE ;09 @@ -2836,7 +2952,7 @@ Is2c0r1 bsf LR_BUF,0 ;07 Is2c1r1 bsf LR_BUF,1 ;07 movlw low Is3c2r1 ;08 movwf LR_STATE ;09 - goto InNothing ;10-11 + goto InSecond ;10-11 Is2c2r1 bsf LR_BUF,2 ;07 movlw low Is3c3r1 ;08 movwf LR_STATE ;09 @@ -2844,7 +2960,7 @@ Is2c2r1 bsf LR_BUF,2 ;07 Is2c3r1 bsf LR_BUF,3 ;07 movlw low Is3c4r1 ;08 movwf LR_STATE ;09 - goto InNothing ;10-11 + goto InFourth ;10-11 Is2c4r1 bsf LR_BUF,4 ;07 movlw low Is3c5r1 ;08 movwf LR_STATE ;09 @@ -2852,7 +2968,7 @@ Is2c4r1 bsf LR_BUF,4 ;07 Is2c5r1 bsf LR_BUF,5 ;07 movlw low Is3c6r1 ;08 movwf LR_STATE ;09 - goto InNothing ;10-11 + goto InSixth ;10-11 Is2c6r1 bsf LR_BUF,6 ;07 movlw low Is3c7r1 ;08 movwf LR_STATE ;09 @@ -2868,7 +2984,7 @@ Is3c0r1 bsf LR_BUF,0 ;07 Is3c1r1 bsf LR_BUF,1 ;07 movlw low Is4c2r1 ;08 movwf LR_STATE ;09 - goto InNothing ;10-11 + goto InSecond ;10-11 Is3c2r1 bsf LR_BUF,2 ;07 movlw low Is4c3r1 ;08 movwf LR_STATE ;09 @@ -2876,7 +2992,7 @@ Is3c2r1 bsf LR_BUF,2 ;07 Is3c3r1 bsf LR_BUF,3 ;07 movlw low Is4c4r1 ;08 movwf LR_STATE ;09 - goto InNothing ;10-11 + goto InFourth ;10-11 Is3c4r1 bsf LR_BUF,4 ;07 movlw low Is4c5r1 ;08 movwf LR_STATE ;09 @@ -2884,7 +3000,7 @@ Is3c4r1 bsf LR_BUF,4 ;07 Is3c5r1 bsf LR_BUF,5 ;07 movlw low Is4c6r1 ;08 movwf LR_STATE ;09 - goto InNothing ;10-11 + goto InSixth ;10-11 Is3c6r1 bsf LR_BUF,6 ;07 movlw low Is4c7r1 ;08 movwf LR_STATE ;09 @@ -2900,7 +3016,7 @@ Is4c0r1 bsf LR_BUF,0 ;07 Is4c1r1 bsf LR_BUF,1 ;07 movlw low Is5c2r1 ;08 movwf LR_STATE ;09 - goto InNothing ;10-11 + goto InSecond ;10-11 Is4c2r1 bsf LR_BUF,2 ;07 movlw low Is5c3r1 ;08 movwf LR_STATE ;09 @@ -2908,7 +3024,7 @@ Is4c2r1 bsf LR_BUF,2 ;07 Is4c3r1 bsf LR_BUF,3 ;07 movlw low Is5c4r1 ;08 movwf LR_STATE ;09 - goto InNothing ;10-11 + goto InFourth ;10-11 Is4c4r1 bsf LR_BUF,4 ;07 movlw low Is5c5r1 ;08 movwf LR_STATE ;09 @@ -2916,7 +3032,7 @@ Is4c4r1 bsf LR_BUF,4 ;07 Is4c5r1 bsf LR_BUF,5 ;07 movlw low Is5c6r1 ;08 movwf LR_STATE ;09 - goto InNothing ;10-11 + goto InSixth ;10-11 Is4c6r1 bsf LR_BUF,6 ;07 movlw low Is5c7r1 ;08 movwf LR_STATE ;09