;;; 80 characters wide please ;;;;;;;;;;;;;;;;;;;;;;;;;; 8-space tabs please ;;; ; ;;; ;;;;; TashTwenty: Single-Chip DCD Interface ;;; ; ;;; 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 ;;; ;;; ;;; ; .--------. ; ; Supply -|01 \/ 14|- Ground ; ; !ENBL ---> RA5 -|02 13|- RA0 ---> Next !ENBL ; ; PH3 ---> RA4 -|03 12|- RA1 <--- PH0 ; ; PH2 ---> RA3 -|04 11|- RA2 <--- PH1 ; ; WR ---> RC5 -|05 10|- RC0 ---> MMC SCK ; ; RD <--- RC4 -|06 09|- RC1 <--- MMC MISO ; ; MMC !CS <--- RC3 -|07 08|- RC2 ---> MMC MOSI ; ; '--------' ; ;;; ;;; ;;; Assembler Directives ;;; list P=PIC16F1825, F=INHX32, ST=OFF, MM=OFF, R=DEC, X=ON #include P16F1825.inc __config _CONFIG1, _FOSC_INTOSC & _WDTE_OFF & _PWRTE_ON & _MCLRE_OFF & _CP_OFF & _CPD_OFF & _BOREN_OFF & _CLKOUTEN_OFF & _IESO_OFF & _FCMEN_OFF ;_FOSC_INTOSC Internal oscillator, I/O on RA5 ;_WDTE_OFF Watchdog timer disabled ;_PWRTE_ON Keep in reset for 64 ms on start ;_MCLRE_OFF RA3/!MCLR is RA3 ;_CP_OFF Code protection off ;_CPD_OFF Data memory protection off ;_BOREN_OFF Brownout reset off ;_CLKOUTEN_OFF CLKOUT disabled, I/O on RA4 ;_IESO_OFF Internal/External switch not needed ;_FCMEN_OFF Fail-safe clock monitor not needed __config _CONFIG2, _WRT_OFF & _PLLEN_ON & _STVREN_ON & _LVP_OFF ;_WRT_OFF Write protection off ;_PLLEN_ON 4x PLL on ;_STVREN_ON Stack over/underflow causes reset ;_LVP_OFF High-voltage on Vpp to program ;;; Macros ;;; DELAY macro value ;Delay 3*W cycles, set W to 0 movlw value decfsz WREG,F bra $-1 endm DNOP macro bra $+1 endm ;;; Constants ;;; ;FLAGS: ABORTED equ 7 ;Set if a transmit or receive operation was aborted RNFERR equ 6 ;Set if host tries to access a too-high block address DEVSEL1 equ 1 ;MSB of which device is selected DEVSEL0 equ 0 ;LSB of which device is selected ;M_FLAGS: M_FAIL equ 7 ;Set when there's been a failure on the MMC interface M_CMDLR equ 6 ;Set when R3 or R7 is expected (5 bytes), not R1 M_CMDRB equ 5 ;Set when an R1b is expected (busy signal after reply) M_MBRD equ 4 ;Set when a multiblock read is in progress M_MBWR equ 3 ;Set when a multiblock write is in progress M_BKADR equ 2 ;Set when block (rather than byte) addressing is in use M_CDVER equ 1 ;Set when dealing with a V2.0+ card, clear for 1.0 ;DVxFLAG: DV_EXST equ 7 ;Set when device exists ;Firmware version FWVER_3 equ 0x20 FWVER_2 equ 0x21 FWVER_1 equ 0x11 FWVER_0 equ 0x28 ;;; Variable Storage ;;; cblock 0x70 ;Bank-common registers FLAGS ;You've got to have flags GROUPS ;Count of groups to transmit, count of groups received CRC16H ;High byte of the CRC16 register CRC16L ;Low byte of the CRC16 register M_FLAGS ;MMC flags M_CMDN ;The MMC command to be sent, later the R1 response byte M_ADR3 ;First (high) byte of the address, first byte of R3/R7 response M_ADR2 ;Second byte of the address, second byte of R3/R7 response M_ADR1 ;Third byte of the address, third byte of R3/R7 response M_ADR0 ;Fourth (low) byte of the address, last byte of R3/R7 response TEMP ;Various purposes TEMP2 ;Various purposes D3 D2 D1 D0 endc cblock 0x20 ;Bank 0 registers ;Partition struct DV0FLAG ;Device 0 flags DV0LN_2 ;Device 0 LBA length DV0LN_1 ; " DV0LN_0 ; " DV0ST_3 ;Device 0 start LBA DV0ST_2 ; " DV0ST_1 ; " DV0ST_0 ; " DV1FLAG ;Device 1 flags DV1LN_2 ;Device 1 LBA length DV1LN_1 ; " DV1LN_0 ; " DV1ST_3 ;Device 1 start LBA DV1ST_2 ; " DV1ST_1 ; " DV1ST_0 ; " DV2FLAG ;Device 2 flags DV2LN_2 ;Device 2 LBA length DV2LN_1 ; " DV2LN_0 ; " DV2ST_3 ;Device 2 start LBA DV2ST_2 ; " DV2ST_1 ; " DV2ST_0 ; " DV3FLAG ;Device 3 flags DV3LN_2 ;Device 3 LBA length DV3LN_1 ; " DV3LN_0 ; " DV3ST_3 ;Device 3 start LBA DV3ST_2 ; " DV3ST_1 ; " DV3ST_0 ; " ;Error (high nibble) and unknown command (low nibble) log LOG_00 LOG_01 LOG_02 LOG_03 LOG_04 LOG_05 LOG_06 LOG_07 LOG_08 LOG_09 LOG_0A LOG_0B LOG_0C LOG_0D LOG_0E LOG_0F LOG_10 LOG_11 LOG_12 LOG_13 LOG_14 LOG_15 LOG_16 LOG_17 LOG_18 LOG_19 LOG_1A LOG_1B LOG_1C LOG_1D LOG_1E LOG_1F ;Card info CARDINF ;TODO Unused 7 bytes UNUSED6 UNUSED5 UNUSED4 UNUSED3 UNUSED2 UNUSED1 UNUSED0 endc cblock 0x68 ;Top of data buffer (receive shorthand) RC_SYNC ;Sync byte RC_CMDG ;Command groups + 0x80 RC_RSPG ;Response groups + 0x80 RC_CMDN ;Command number RC_BLKS ;Block count RC_ADRH ;Block address high RC_ADRM ;Block address middle RC_ADRL ;Block address low endc cblock 0x68 ;Top of data buffer (transmit shorthand) TX_CMDN ;Command number TX_BLKS ;Block count TX_STAT ;Status TX_PAD1 ;Pad byte TX_PAD2 ;Pad byte TX_PAD3 ;Pad byte TX_CSUM ;Checksum, if reply is only one group long endc ;;; Vectors ;;; org 0x0 ;Reset vector bra Init org 0x4 ;Interrupt vector ;;; Interrupt Handler ;;; ;BSR must always be at 0 when interrupts are on Interrupt lslf PORTA,W ;32 entries in the jump table, each has four brw ; instructions; jump to the one matching state nop ;We expect RA0 to be high nop ; " IntEn0 movlb 7 ;This is the suspend state, so we should never clrf IOCAF ; get here unless it's a blip on one of the retfie ; state lines - if it is, clear and return and nop ; just hope timing isn't too badly wrecked IntEn1 movlb 7 ;This is the communication state, so we should clrf IOCAF ; never get here unless it's a blip on one of retfie ; the state lines - if it is, clear and return nop ; and just hope timing isn't too badly wrecked IntEn2 bsf PORTC,RC4 ;Being in state 2 (idle) without first going to bra IntAbort ; state 3 means mac wants to abort the nop ; operation in progress nop ; " IntEn3 bra IntDoneReceive ;This means mac is done and is waiting for nop ; !HSHK to be deasserted nop ; " nop ; " IntEn4 bsf PORTC,RC4 ;This state (reset) is two states away from the bra IntAbort ; communication state, which is strange, but nop ; assume that it means mac wants to abort the nop ; operation in progress IntEn5 bcf PORTC,RC4 ;Now this is really weird; why would mac go to bra Interrupt ; this state (drive RD low) in the middle of nop ; communication? Whatever, drive RD low and nop ; immediately circle back until state changes IntEn6 bsf PORTC,RC4 ;Now this is really weird; why would mac go to bra Interrupt ; this state (drive RD high) in the middle of nop ; communication? Whatever, drive RD high and nop ; immediately circle back until state changes IntEn7 bsf PORTC,RC4 ;Now this is really weird; why would mac go to bra Interrupt ; this state (drive RD high) in the middle of nop ; communication? Whatever, drive RD high and nop ; immediately circle back until state changes IntEnNx bsf PORTC,RC4 ;Now this is really REALLY weird; why would mac bra IntAbort ; decide to talk to the next device in mid- nop ; communication? Whatever, drive RD high and nop ; force an unexplained return to the idle state bsf PORTC,RC4 ;Now this is really REALLY weird; why would mac bra IntAbort ; decide to talk to the next device in mid- nop ; communication? Whatever, drive RD high and nop ; force an unexplained return to the idle state bsf PORTC,RC4 ;Now this is really REALLY weird; why would mac bra IntAbort ; decide to talk to the next device in mid- nop ; communication? Whatever, drive RD high and nop ; force an unexplained return to the idle state bsf PORTC,RC4 ;Now this is really REALLY weird; why would mac bra IntAbort ; decide to talk to the next device in mid- nop ; communication? Whatever, drive RD high and nop ; force an unexplained return to the idle state bsf PORTC,RC4 ;Now this is really REALLY weird; why would mac bra IntAbort ; decide to talk to the next device in mid- nop ; communication? Whatever, drive RD high and nop ; force an unexplained return to the idle state bsf PORTC,RC4 ;Now this is really REALLY weird; why would mac bra IntAbort ; decide to talk to the next device in mid- nop ; communication? Whatever, drive RD high and nop ; force an unexplained return to the idle state bsf PORTC,RC4 ;Now this is really REALLY weird; why would mac bra IntAbort ; decide to talk to the next device in mid- nop ; communication? Whatever, drive RD high and nop ; force an unexplained return to the idle state bsf PORTC,RC4 ;Now this is really REALLY weird; why would mac bra IntAbort ; decide to talk to the next device in mid- nop ; communication? Whatever, drive RD high and nop ; force an unexplained return to the idle state IntNEn bsf PORTC,RC4 ;Now this is really REALLY weird; why would mac bra IntAbort ; decide to deassert !ENBL mid-communication? nop ; Whatever, drive RD high and force an nop ; unexplained return to the idle state bsf PORTC,RC4 ;Now this is really REALLY weird; why would mac bra IntAbort ; decide to deassert !ENBL mid-communication? nop ; Whatever, drive RD high and force an nop ; unexplained return to the idle state bsf PORTC,RC4 ;Now this is really REALLY weird; why would mac bra IntAbort ; decide to deassert !ENBL mid-communication? nop ; Whatever, drive RD high and force an nop ; unexplained return to the idle state bsf PORTC,RC4 ;Now this is really REALLY weird; why would mac bra IntAbort ; decide to deassert !ENBL mid-communication? nop ; Whatever, drive RD high and force an nop ; unexplained return to the idle state bsf PORTC,RC4 ;Now this is really REALLY weird; why would mac bra IntAbort ; decide to deassert !ENBL mid-communication? nop ; Whatever, drive RD high and force an nop ; unexplained return to the idle state bsf PORTC,RC4 ;Now this is really REALLY weird; why would mac bra IntAbort ; decide to deassert !ENBL mid-communication? nop ; Whatever, drive RD high and force an nop ; unexplained return to the idle state bsf PORTC,RC4 ;Now this is really REALLY weird; why would mac bra IntAbort ; decide to deassert !ENBL mid-communication? nop ; Whatever, drive RD high and force an nop ; unexplained return to the idle state bsf PORTC,RC4 ;Now this is really REALLY weird; why would mac bra IntAbort ; decide to deassert !ENBL mid-communication? nop ; Whatever, drive RD high and force an nop ; unexplained return to the idle state bsf PORTC,RC4 ;Now this is really REALLY weird; why would mac bra IntAbort ; decide to deassert !ENBL mid-communication? nop ; Whatever, drive RD high and force an nop ; unexplained return to the idle state bsf PORTC,RC4 ;Now this is really REALLY weird; why would mac bra IntAbort ; decide to deassert !ENBL mid-communication? nop ; Whatever, drive RD high and force an nop ; unexplained return to the idle state bsf PORTC,RC4 ;Now this is really REALLY weird; why would mac bra IntAbort ; decide to deassert !ENBL mid-communication? nop ; Whatever, drive RD high and force an nop ; unexplained return to the idle state bsf PORTC,RC4 ;Now this is really REALLY weird; why would mac bra IntAbort ; decide to deassert !ENBL mid-communication? nop ; Whatever, drive RD high and force an nop ; unexplained return to the idle state bsf PORTC,RC4 ;Now this is really REALLY weird; why would mac bra IntAbort ; decide to deassert !ENBL mid-communication? nop ; Whatever, drive RD high and force an nop ; unexplained return to the idle state bsf PORTC,RC4 ;Now this is really REALLY weird; why would mac bra IntAbort ; decide to deassert !ENBL mid-communication? nop ; Whatever, drive RD high and force an nop ; unexplained return to the idle state bsf PORTC,RC4 ;Now this is really REALLY weird; why would mac bra IntAbort ; decide to deassert !ENBL mid-communication? nop ; Whatever, drive RD high and force an nop ; unexplained return to the idle state bsf PORTC,RC4 ;Now this is really REALLY weird; why would mac bra IntAbort ; decide to deassert !ENBL mid-communication? nop ; Whatever, drive RD high and force an nop ; unexplained return to the idle state IntDoneReceive movlp high RecvDecode ;Decode the data we've received call RecvDecode ; " bsf PORTC,RC4 ;Deassert !HSHK to acknowledge receive is done IntDRc0 decf PORTA,W ;Check the current state xorlw B'00000110' ;If it's still 3, mac hasn't acknowledged our btfsc STATUS,Z ; acknowledgment of the end of received data bra IntDRc0 ; yet, so loop again xorlw B'00000010' ;If it's anything else but 2 (idle), something btfss STATUS,Z ; weird's going on, so abort bra IntAbort ; " movlb 7 ;Clear the interrupt that got us here and any clrf IOCAF ; we received after that movlb 31 ;Swallow the interrupt return address and decf STKPTR,F ; instead return to who called receiver movlb 0 ; without reenabling interrupts movlp 0 ;Reset PCLATH to where we're returning return ; " IntAbort movlb 7 ;Clear the interrupt that got us here and any clrf IOCAF ; we received after that movlb 31 ;Swallow the return address where the PC was decf STKPTR,F ; when the interrupt happened movlb 0 ; " bsf FLAGS,ABORTED ;Raise the aborted flag movlp 0 ;Reset PCLATH to where we're returning return ;Return to caller without reenabling interrupts ;;; Init ;;; Init banksel OSCCON ;32 MHz (w/PLL) high-freq internal oscillator movlw B'11110000' movwf OSCCON banksel IOCAP ;When interrupts are on, any change on !ENBL, movlw B'00111100' ; PH3, PH2, or PH1 triggers one; this is what movwf IOCAP ; gets us out of the endless receive loop movwf IOCAN banksel SSPCON1 ;SSP SPI master mode, clock set by baud rate movlw B'00101010' ; generator to 400 kHz, clock idles low, data movwf SSPCON1 ; lines change on falling edge, data sampled on movlw B'01000000' ; rising edge (CKP=0, CKE=1, SMP=0) movwf SSP1STAT movlw 19 movwf SSP1ADD banksel ANSELA ;All pins digital, not analog clrf ANSELA clrf ANSELC banksel LATA ;Next !ENBL off, RD and !CS high to start movlw B'00111111' movwf LATA movwf LATC banksel TRISA ;State pins inputs, RA0 output, WR input, RD movlw B'00111110' ; tristated to start, MISO input, !CS, MOSI, movwf TRISA ; and SCK output movlw B'00110010' movwf TRISC movlw B'00001000' ;Interrupt on PORTA pin change enabled, but movwf INTCON ; interrupt subsystem off for now movlw 0x20 ;Zero all bank 0 registers movwf FSR0H clrf FSR0L movlw 72 movwf TEMP movlw 0 ClrLoop movwi FSR0++ decfsz TEMP,F bra ClrLoop movlb 0 ;Start BSR at 0 movlw 11 ;Delay approximately 1 ms to allow the MMC card movwf TEMP ; to come up - do not call MmcInit before this DelayMs DELAY 242 ; has been done decfsz TEMP,F ; " bra DelayMs ; " call MmcInit ;Initialize! btfsc M_FLAGS,M_FAIL ;If we couldn't initialize the card, give up goto NoDevices ; and pass !ENBL through to next device movlb 4 ;Now that we're initialized, crank the speed movlw B'00100001' ; of the SPI interface up to 2 MHz movwf SSPCON1 ; " movlb 0 ; " movlw 0x51 ;Set up a read command for the MMC card (R1- movwf M_CMDN ; type response) bcf M_FLAGS,M_CMDLR ; " bcf M_FLAGS,M_CMDRB ; " clrf M_ADR3 ;Point the card address to the master boot clrf M_ADR2 ; record clrf M_ADR1 ; " clrf M_ADR0 ; " bcf PORTC,RC3 ;Assert !CS call MmcCmd ;Send the MMC command btfsc M_FLAGS,M_FAIL ;If the operation failed, give up and just pass goto NoDevices ; !ENBL through to the next device movlw 0x20 ;Point FSR0 to the top of the data buffer movwf FSR0H ; " movlw 0x48 ; " movwf FSR0L ; " call MmcReadData ;Read data from the MMC card btfsc M_FLAGS,M_FAIL ;If the operation failed, give up and just pass goto NoDevices ; !ENBL through to the next device bsf PORTC,RC3 ;Deassert !CS movlw 0x22 ;Point FSR0 to the MBR partition table movwf FSR0H ; " movlw 0x06 ; " movwf FSR0L ; " movlw 0x20 ;Point FSR1 to the device structs movwf FSR1H ; " clrf FSR1L ; " movlw 4 ;Loop through all four MBR partition entries movwf TEMP ; " MbrLoop moviw 4[FSR0] ;Check whether the partition type is 0xAF, xorlw 0xAF ; which is the type code for HFS; if it isn't, btfss STATUS,Z ; then move ahead to the next one bra MbrNext ; " moviw 15[FSR0] ;Check whether the partition size > 0xFFFFFF; btfss STATUS,Z ; if it is, it's too big, move ahead to the bra MbrNext ; next one moviw 11[FSR0] ;Copy the partition start LBA, converting the movwi 4[FSR1] ; little-endian number to big-endian as we go moviw 10[FSR0] ; " movwi 5[FSR1] ; " moviw 9[FSR0] ; " movwi 6[FSR1] ; " moviw 8[FSR0] ; " movwi 7[FSR1] ; " moviw 14[FSR0] ;Copy the partition LBA size, converting the movwi 1[FSR1] ; little-endian number to big-endian as we go moviw 13[FSR0] ; " movwi 2[FSR1] ; " moviw 12[FSR0] ; " movwi 3[FSR1] ; " movlw 1 << DV_EXST ;Set the device-exists flag for this partition movwi 0[FSR1] ; " addfsr FSR1,8 ;Advance device struct pointer to next entry MbrNext addfsr FSR0,16 ;Advance the MBR pointer to the next entry decfsz TEMP,F ;If we have partition entries left to scan, bra MbrLoop ; loop for the next one moviw 0[FSR0] ;After all that, check whether the 0xAA55 (LE) xorlw 0x55 ; MBR signature is present; if it isn't, then btfss STATUS,Z ; all we did above was for nothing because this goto NoDevices ; isn't a valid MBR, so just pass !ENBL through moviw 1[FSR0] ; " xorlw 0xAA ; " btfss STATUS,Z ; " goto NoDevices ; " btfss DV0FLAG,DV_EXST ;If we didn't detect any valid partitions, just goto NoDevices ; pass !ENBL through; if we have at least one, goto WaitEnbl ; enter the normal idle loop and wait for !ENBL ;;; Mainline Code ;;; GetCommand bsf PORTC,RC4 ;Deassert !HSHK and prepare to receive movlp high Receive ;Initiate receive call Receive ; " btfsc FLAGS,ABORTED ;If it was aborted, return to idle loop return ; " call CheckChecksum ;Calculate the checksum of the received block btfss STATUS,Z ;If the checksum was bad, send a NAK bra NakCommand ; " movf RC_CMDN,W ;If the command number is 0x00, do a read btfsc STATUS,Z ; " bra CmdRead ; " addlw -1 ;If the command number is 0x01, do a write btfsc STATUS,Z ; " bra CmdWrite ; " addlw -2 ;If the command number is 0x03, get controller btfsc STATUS,Z ; status (identify device) bra CmdStatus ; " addlw -62 ;If the command number is 0x41, do a continued btfsc STATUS,Z ; write (write routine will tell this apart) bra CmdWrite ; " bra CmdUnknown ;If none of the above, fake a response CmdUnknown movf RC_CMDN,W ;Save the unknown command's number since it's movwf TEMP2 ; about to be overwritten call ClearResponse ;Clear the buffer according to expectations movf TEMP2,W ;Our reply is going to be the command number movwf TX_CMDN ; with its MSB set, by convention, but data bsf TX_CMDN,7 ; will be all zeroes clrf FSR0H ;Point FSR0 at error/unknown command log bsf FSR0H,5 ; " clrf FSR0L ; " bsf FSR0L,5 ; " andlw B'0011111' ;Mask off the low 5 bits of the command code addwf FSR0L,F ; " movf INDF0,W ;If the count (low nibble) is already at 15, andlw B'00001111' ; keep it there; if it's below 15, increment it xorlw B'00001111' ; " btfss STATUS,Z ; " incf INDF0,F ; " call CalcChecksum ;Calculate the checksum of placeholder reply movlp high Transmit ;Initiate transmission; if it's aborted, we call Transmit ; don't actually do anything differently return ;Done, hope the host doesn't mind NakCommand movlw 1 ;A NAK is a blank one-group command buffer with movwf GROUPS ; a command number of 0x7F movlw 0x7F ; " movwf TX_CMDN ; " clrf TX_BLKS ; " clrf TX_STAT ; " clrf TX_PAD1 ; " clrf TX_PAD2 ; " clrf TX_PAD3 ; " movlw 0x81 ;We know what the checksum will be, so just movwf TX_CSUM ; hardcode it movlp high Transmit ;Initiate transmission; if it's aborted, we call Transmit ; don't actually do anything differently return ;Done ErrorSetup movlb 31 ;Insert the latter half of this function into movf TOSH,W ; the call stack, then return to the caller so movwf TEMP ; the caller can retlw a status code that we movf TOSL,W ; can act on movwf TEMP2 ; " movlw high ErrSet0 ; " movwf TOSH ; " movlw low ErrSet0 ; " movwf TOSL ; " incf STKPTR,F ; " movf TEMP,W ; " movwf TOSH ; " movf TEMP2,W ; " movwf TOSL ; " movlb 0 ; " return ; " ErrSet0 movf WREG,W ;If the caller returned status 0, just return btfsc STATUS,Z ; to idle loop return ; " movwf TX_PAD1 ;Store error code in first transmitter pad byte clrf FSR0H ;Point FSR0 at error/unknown command log bsf FSR0H,5 ; " clrf FSR0L ; " bsf FSR0L,5 ; " andlw B'0011111' ;Mask off the low 5 bits of the error code (we addwf FSR0L,F ; need to keep to 32 or fewer errors) movf INDF0,W ;If the error count (high nibble) is already at andlw B'11110000' ; 15, keep it there; if it's below 15, xorlw B'11110000' ; increment it movlw 0x10 ; " btfsc STATUS,Z ; " addwf INDF0,F ; " bsf PORTC,RC3 ;Deassert !CS movlw 1 ;Communicate failure to the host by setting the movwf GROUPS ; MSB of the status byte and sending only the bsf TX_STAT,7 ; header group call CalcChecksum ;Calculate the checksum movlp high Transmit ;Initiate transmission; if it's aborted, we call Transmit ; don't actually do anything differently return ;Done CmdRead call ErrorSetup ;Set up error handling movf RC_BLKS,W ;Move the block count from receiver position to movwf TX_BLKS ; transmitter position movlw 0x80 ;Command number is the read command with the movwf TX_CMDN ; MSB set clrf TX_STAT ;A zero status means all is well call MmcStopOngoing ;Stop any multiblock read or write btfsc M_FLAGS,M_FAIL ;If MMC operation failed, report the error retlw 0x01 ; " call TranslateAddr ;Translate block address to MMC block address btfsc FLAGS,RNFERR ;If we couldn't translate this block address to retlw 0x02 ; an MMC address, report the error call MmcConvAddr ;Convert the address if necessary btfsc M_FLAGS,M_FAIL ;If MMC operation failed, report the error retlw 0x03 ; " clrf TX_PAD1 ;Clear the padding bytes (don't do this before clrf TX_PAD2 ; we convert the address since they overlap clrf TX_PAD3 ; with the address bytes) ;TODO clear 20 tag bytes too? movlw 0x52 ;Set up a read command for the MMC card (R1- movwf M_CMDN ; type response) bcf M_FLAGS,M_CMDLR ; " bcf M_FLAGS,M_CMDRB ; " bcf PORTC,RC3 ;Assert !CS call MmcCmd ;Send the MMC command btfsc M_FLAGS,M_FAIL ;If MMC operation failed, report the error retlw 0x04 ; " bsf M_FLAGS,M_MBRD ;Set the flag for an ongoing multiblock read CmdRea0 movlw 0x20 ;Point FSR0 past the six header bytes and the movwf FSR0H ; 20 'tag' bytes to where the real data starts movlw 0x62 ; " movwf FSR0L ; " call MmcReadData ;Read data from the MMC card btfsc M_FLAGS,M_FAIL ;If MMC operation failed, report the error retlw 0x05 ; " decf TX_BLKS,W ;If the blocks-remaining counter is at one, btfsc STATUS,Z ; stop the multiblock read here before sending call MmcStopOngoing ; our response to the mac btfsc M_FLAGS,M_FAIL ;If MMC operation failed, report the error retlw 0x06 ; " movlw 77 ;Set the group count to 77 (512 bytes of data, movwf GROUPS ; 20 'tag' bytes, 6 byte header, checksum byte) call CalcChecksum ;Calculate the checksum on our response movlp high Transmit ;Initiate transmission call Transmit ; " btfsc FLAGS,ABORTED ;If the command was aborted, return to idle retlw 0x00 ; loop call MmcIncAddr ;Increment address for next read decfsz TX_BLKS,F ;Decrement the block count; if it hits zero, bra CmdRea0 ; that's all the reading we were requested to retlw 0x00 ; do, so call it done CmdWrite call ErrorSetup ;Set up error handling movf RC_BLKS,W ;Move the block count from receiver position to movwf TX_BLKS ; transmitter position movlw 0x81 ;Command number is the write command with the movwf TX_CMDN ; MSB set clrf TX_STAT ;A zero status means all is well movf RC_CMDN,W ;If this is a continued write, we don't want to xorlw 0x41 ; set up the write anew, so skip ahead btfsc STATUS,Z ; " bra CmdWriteCont ; " call MmcStopOngoing ;Stop any multiblock read or write btfsc M_FLAGS,M_FAIL ;If MMC operation failed, report the error retlw 0x07 ; " call TranslateAddr ;Translate block address to MMC block address btfsc FLAGS,RNFERR ;If we couldn't translate this block address to retlw 0x08 ; an MMC address, report the error call MmcConvAddr ;Convert the address if necessary btfsc M_FLAGS,M_FAIL ;If MMC operation failed, report the error retlw 0x09 ; " movlw 0x59 ;Set up a write command for the MMC card (R1- movwf M_CMDN ; type reply) bcf M_FLAGS,M_CMDLR ; " bcf M_FLAGS,M_CMDRB ; " bcf PORTC,RC3 ;Assert !CS call MmcCmd ;Send the MMC command btfsc M_FLAGS,M_FAIL ;If MMC operation failed, report the error retlw 0x0A ; " bsf M_FLAGS,M_MBWR ;Set the flag for an ongoing multiblock write CmdWriteCont btfss M_FLAGS,M_MBWR ;If for some reason we got here without there retlw 0x0B ; being a multiblock write going on, error movlw 0x20 ;Point FSR0 past the sync, length, header, and movwf FSR0H ; tag bytes, and to the data we'll be writing movlw 0x65 ; " movwf FSR0L ; " call MmcWriteData ;Write data to the MMC card btfsc M_FLAGS,M_FAIL ;If MMC operation failed, report the error retlw 0x0C ; " decf RC_BLKS,W ;If the blocks-remaining counter is at one, btfsc STATUS,Z ; stop the multiblock write here before sending call MmcStopOngoing ; our response to the mac btfsc M_FLAGS,M_FAIL ;If MMC operation failed, report the error retlw 0x0D ; " clrf TX_PAD1 ;Clear the padding bytes (don't do this before clrf TX_PAD2 ; we convert the address since they overlap clrf TX_PAD3 ; with the address bytes) movlw 1 ;Acknowledgment is one group in length movwf GROUPS ; " call CalcChecksum ;Calculate the checksum on our response movlp high Transmit ;Initiate transmission; if it's aborted, we call Transmit ; don't actually do anything differently retlw 0x00 ;Done CmdStatus call ClearResponse ;Clear the buffer for our response movlw 0x83 ;Command number is the status command with the movwf TX_CMDN ; MSB set clrf TX_STAT ;A zero status means all is well clrf TX_BLKS ;Clear the block count as it's not relevant clrf TX_PAD1 ;Clear the padding bytes clrf TX_PAD2 ; " clrf TX_PAD3 ; " movlw 0x20 ;Point FSR0 at the appropriate struct for the movwf FSR0H ; selected device clrf FSR0L ; " btfsc FLAGS,DEVSEL1 ; " addfsr FSR0,16 ; " btfsc FLAGS,DEVSEL0 ; " addfsr FSR0,8 ; " movlw 0x20 ;Point FSR1 past the six header bytes to where movwf FSR1H ; the real data starts movlw 0x4E ; " movwf FSR1L ; " movlw 0x01 ;Device manufacturer is 0x0100, not sure if movwi 2[FSR1] ; anybody cares movlw 0xF6 ;Device is mountable, readable, writeable, movwi 4[FSR1] ; ejectable (?), icon_included, & disk_in_place moviw 3[FSR0] ;Copy the LBA length of the partition into the movwi 7[FSR1] ; block size of the drive moviw 2[FSR0] ; " movwi 6[FSR1] ; " moviw 1[FSR0] ; " movwi 5[FSR1] ; " addfsr FSR1,7 ;Decrement the block size of the drive because movlw 0xFF ; it appears that the block size of the drive addwf INDF1,F ; is actually the maximum block on the drive addfsr FSR1,-1 ; TODO look into this further addwfc INDF1,F ; " addfsr FSR1,-1 ; " addwfc INDF1,F ; " addfsr FSR1,7 ;Point FSR1 to manufacturer info field moviw 0[FSR0] ;Copy the partition information for this device movwi FSR1++ ; into the first 8 bytes moviw 1[FSR0] ; " movwi FSR1++ ; " moviw 2[FSR0] ; " movwi FSR1++ ; " moviw 3[FSR0] ; " movwi FSR1++ ; " moviw 4[FSR0] ; " movwi FSR1++ ; " moviw 5[FSR0] ; " movwi FSR1++ ; " moviw 6[FSR0] ; " movwi FSR1++ ; " moviw 7[FSR0] ; " movwi FSR1++ ; " movlw 0x20 ;Point FSR0 to remaining 40 bytes in bank 0 movwf FSR0L ; " movlw 40 ;Copy 40 bytes to the manufacturer info field movwf TEMP ; " CmdSta0 moviw FSR0++ ; " movwi FSR1++ ; " decfsz TEMP,F ; " bra CmdSta0 ; " movlw FWVER_3 ;Copy firmware version into last four bytes of movwi FSR1++ ; manufacturer info field and leave FSR1 movlw FWVER_2 ; pointing to icon field movwi FSR1++ ; " movlw FWVER_1 ; " movwi FSR1++ ; " movlw FWVER_0 ; " movwi FSR1++ ; " movlw high Icon | 0x80;Point FSR0 to the icon table movwf FSR0H ; " movlw low Icon ; " movwf FSR0L ; " clrf TEMP ;Copy 256 bytes to the icon field CmdSta1 moviw FSR0++ ; " movwi FSR1++ ; " decfsz TEMP,F ; " bra CmdSta1 ; " movlw 0x0A ;The credits movwi FSR1++ ; " movlw 'T' ; " movwi FSR1++ ; " movlw 'a' ; " movwi FSR1++ ; " movlw 's' ; " movwi FSR1++ ; " movlw 'h' ; " movwi FSR1++ ; " movlw 'T' ; " movwi FSR1++ ; " movlw 'w' ; " movwi FSR1++ ; " movlw 'e' ; " movwi FSR1++ ; " movlw 'n' ; " movwi FSR1++ ; " movlw 't' ; " movwi FSR1++ ; " movlw 'y' ; " movwi FSR1++ ; " call CalcChecksum ;Calculate the checksum on our response movlp high Transmit ;Initiate transmission; if it's aborted, we call Transmit ; don't actually do anything differently return ;Done ;;; Subprograms ;;; ;Calculate the checksum of the block about to be transmitted, containing ; GROUPS * 7 bytes. Trashes TEMP, TEMP2, and FSR0. CalcChecksum movlw 0x20 ;Point FSR0 at the top of the data buffer movwf FSR0H ; " movlw 0x48 ; " movwf FSR0L ; " movf GROUPS,W ;Copy the group count into TEMP movwf TEMP ; " clrf TEMP2 ;Zero the running sum (mod 256) bra CalcCh1 ;Jump the first add so we sum one less than the CalcCh0 moviw FSR0++ ; total bytes in the block and can write the addwf TEMP2,F ; checksum to the very last byte position CalcCh1 moviw FSR0++ ;Add the bytes in this group to the running sum addwf TEMP2,F ; " moviw FSR0++ ; " addwf TEMP2,F ; " moviw FSR0++ ; " addwf TEMP2,F ; " moviw FSR0++ ; " addwf TEMP2,F ; " moviw FSR0++ ; " addwf TEMP2,F ; " moviw FSR0++ ; " addwf TEMP2,F ; " decfsz TEMP,F ;Loop until we've summed the last group bra CalcCh0 ; " comf TEMP2,W ;Two's complement the sum so the whole block addlw 1 ; adds up to zero and write it to the block's movwi FSR0++ ; last byte return ;Calculate the checksum of the block just received, starting at the third byte ; of the data buffer and containing GROUPS * 7 bytes. Trashes TEMP, TEMP2, and ; FSR0. CheckChecksum movlw 0x20 ;Point FSR0 to the third byte of the data movwf FSR0H ; buffer movlw 0x4B ; " movwf FSR0L ; " movf GROUPS,W ;Copy the group count into TEMP movwf TEMP ; " clrf TEMP2 ;Zero the running sum (mod 256) CheckC0 moviw FSR0++ ;Add the next seven bytes to the running sum addwf TEMP2,F ; " moviw FSR0++ ; " addwf TEMP2,F ; " moviw FSR0++ ; " addwf TEMP2,F ; " moviw FSR0++ ; " addwf TEMP2,F ; " moviw FSR0++ ; " addwf TEMP2,F ; " moviw FSR0++ ; " addwf TEMP2,F ; " moviw FSR0++ ; " addwf TEMP2,F ; " decfsz TEMP,F ;Loop until we've summed the last group bra CheckC0 ; " movf TEMP2,F ;Set Z if block sum is 0 and checksum is good return ;Clear the data buffer for the response to a command according to the expected ; response length according to mac, setting GROUPS to the number of groups to ; be sent. Trashes TEMP and FSR0. ClearResponse movlw 0x20 ;Point FSR0 at the top of the data buffer movwf FSR0H ; " movlw 0x48 ; " movwf FSR0L ; " movf RC_RSPG,W ;Snuff the top bit of the number of groups in andlw B'01111111' ; the expected response and copy this into movwf GROUPS ; the group count as well as a temporary movwf TEMP ; counter movlw 0 ;Zero is what we're setting the buffer to ClearR0 movwi FSR0++ ;Write seven zeroes to the buffer movwi FSR0++ ; " movwi FSR0++ ; " movwi FSR0++ ; " movwi FSR0++ ; " movwi FSR0++ ; " movwi FSR0++ ; " decfsz TEMP,F ;Loop until we've zeroed the last group bra ClearR0 ; " return ;Translate the address from a command into an address on the MMC card. Sets ; RNFERR if (considering the block count) the command would address memory that ; is beyond the boundary of the drive. TranslateAddr bcf FLAGS,RNFERR ;Assume no error to start with movlw 0x20 ;Point FSR0 at the appropriate struct for the movwf FSR0H ; selected device clrf FSR0L ; " btfsc FLAGS,DEVSEL1 ; " addfsr FSR0,16 ; " btfsc FLAGS,DEVSEL0 ; " addfsr FSR0,8 ; " decf RC_BLKS,W ;Add the block count (less one because it's addwf RC_ADRL,F ; one-relative) to the block address so we can movlw 0 ; do a full boundary check addwfc RC_ADRM,F ; " addwfc RC_ADRH,F ; " moviw 3[FSR0] ;Compare the maximum block address that would subwf RC_ADRL,W ; be accessed by this command to the LBA length moviw 2[FSR0] ; of the partition; if the maximum block subwfb RC_ADRM,W ; address is greater than or equal to the LBA moviw 1[FSR0] ; length of the partition, this is an invalid subwfb RC_ADRH,W ; access and must be rejected; set the record- btfsc STATUS,C ; not-found flag bsf FLAGS,RNFERR ; " decf RC_BLKS,W ;Restore the block address as before subwf RC_ADRL,F ; " movlw 0 ; " subwfb RC_ADRM,F ; " subwfb RC_ADRH,F ; " btfsc FLAGS,RNFERR ;If we had a record-not-found error, we're done return ; " moviw 7[FSR0] ;Add the block address to the start address for addwf RC_ADRL,W ; the partition and store the result in the movwf M_ADR0 ; MMC address registers moviw 6[FSR0] ; " addwfc RC_ADRM,W ; " movwf M_ADR1 ; " moviw 5[FSR0] ; " addwfc RC_ADRH,W ; " movwf M_ADR2 ; " clrf M_ADR3 ; " moviw 4[FSR0] ; " addwfc M_ADR3,F ; " return ;;; MMC Subprograms ;;; ;Initialize MMC card. Sets M_FAIL on fail. Trashes TEMP and TEMP2. MmcInit clrf M_FLAGS ;Make sure flags are all clear to begin with movlb 4 ;This is where all the SSP registers are movlw 10 ;Send 80 clocks on SPI interface to ensure MMC movwf TEMP ; card is started up and in native command mode MmcIni0 movlw 0xFF ; " movwf SSP1BUF ; " btfss SSP1STAT,BF ; " bra $-1 ; " decfsz TEMP,F ; " bra MmcIni0 ; " movlb 0 ;Assert !CS bcf PORTC,RC3 ; " movlw 0x40 ;Send command 0 (expect R1-type response) movwf M_CMDN ; which, with !CS asserted, signals to the card clrf M_ADR3 ; that we want to enter SPI mode clrf M_ADR2 ; " clrf M_ADR1 ; " clrf M_ADR0 ; " bcf M_FLAGS,M_CMDLR ; " bcf M_FLAGS,M_CMDRB ; " call MmcCmd ; " btfsc M_FLAGS,M_FAIL ;If this command failed, unrecognized or return ; missing MMC card, fail the init operation movf M_CMDN,W ;If this command returned any response other xorlw 0x01 ; than 0x01 ('in idle state'), unrecognized MMC btfss STATUS,Z ; card, fail the init operation bsf M_FLAGS,M_FAIL ; " btfss STATUS,Z ; " return ; " bsf M_FLAGS,M_CDVER ;Assume version 2.0+ to begin with clrf TEMP ;Set retry counter to 0 (65536) for later use clrf TEMP2 ; " movlw 0x48 ;Send command 8 (expect R7-type response) to movwf M_CMDN ; check if we're dealing with a V2.0+ card clrf M_ADR3 ; " clrf M_ADR2 ; " movlw 0x01 ; " movwf M_ADR1 ; " movlw 0xAA ; " movwf M_ADR0 ; " bsf M_FLAGS,M_CMDLR ; " bcf M_FLAGS,M_CMDRB ; " call MmcCmd ; " movf M_CMDN,W ;If the command set any error flags or there andlw B'11111110' ; was no response, switch assumptions and guess btfsc STATUS,Z ; that we're dealing with a Version 1 card and btfsc M_FLAGS,M_FAIL ; jump ahead to initialize it bcf M_FLAGS,M_CDVER ; " btfss M_FLAGS,M_CDVER ; " bra MmcIni1 ; " movf M_ADR1,W ;If the command didn't error, but the lower 12 andlw B'00001111' ; bits of the R7 response are something besides xorlw 0x01 ; 0x1AA, we're dealing with an unknown card, so btfss STATUS,Z ; raise the fail flag and return to caller bsf M_FLAGS,M_FAIL ; " movf M_ADR0,W ; " xorlw 0xAA ; " btfss STATUS,Z ; " bsf M_FLAGS,M_FAIL ; " btfsc M_FLAGS,M_FAIL ; " return ; " MmcIni1 movlw 0x77 ;Send command 55 (expect R1-type response), movwf M_CMDN ; which is a prelude to an 'app' command clrf M_ADR3 ; " clrf M_ADR2 ; " clrf M_ADR1 ; " clrf M_ADR0 ; " bcf M_FLAGS,M_CMDLR ; " bcf M_FLAGS,M_CMDRB ; " call MmcCmd ; " movf M_CMDN,W ;If we got a status with any error bits set, andlw B'11111110' ; treat as a command failure btfss STATUS,Z ; " bsf M_FLAGS,M_FAIL ; " btfsc M_FLAGS,M_FAIL ;If this command fails, this is an unknown card return ; so return the failure to caller movlw 0x69 ;Send app command 41 (expect R1-type response) movwf M_CMDN ; to initialize the card, setting the HCS clrf M_ADR3 ; (high-capacity support) bit if we're dealing btfsc M_FLAGS,M_CDVER ; with a V2.0+ card to let the card know that bsf M_ADR3,6 ; we support cards bigger than 4 GB (up to 2 clrf M_ADR2 ; TB) clrf M_ADR1 ; " clrf M_ADR0 ; " bcf M_FLAGS,M_CMDLR ; " bcf M_FLAGS,M_CMDRB ; " call MmcCmd ; " movf M_CMDN,W ;If we got a status with any error bits set, andlw B'11111110' ; treat as a command failure btfss STATUS,Z ; " bsf M_FLAGS,M_FAIL ; " btfsc M_FLAGS,M_FAIL ;If this command fails, this is an unknown card return ; so return the failure to caller btfss M_CMDN,0 ;If it returned an 0x00 status, initialization bra MmcIni2 ; is finished DELAY 40 ;If it returned an 0x01 status, delay for 120 decfsz TEMP,F ; cycles (15 us), decrement the retry counter, bra MmcIni1 ; and try again decfsz TEMP2,F ; " bra MmcIni1 ; " bsf M_FLAGS,M_FAIL ;If we've gone 65536 attempts and the card is return ; still not ready, report failure to caller MmcIni2 movlw 0x7A ;Send command 58 (expect R3-type response) to movwf M_CMDN ; read the operating condition register (OCR) clrf M_ADR3 ; " clrf M_ADR2 ; " clrf M_ADR1 ; " clrf M_ADR0 ; " bsf M_FLAGS,M_CMDLR ; " bcf M_FLAGS,M_CMDRB ; " call MmcCmd ; " movf M_CMDN,W ;If we got a status with any error bits set, btfss STATUS,Z ; treat as a command failure bsf M_FLAGS,M_FAIL ; " btfsc M_FLAGS,M_FAIL ;If this command fails, something is wrong, so return ; return the failure to caller bsf M_FLAGS,M_BKADR ;If the card capacity status (CCS) bit of the btfsc M_ADR3,6 ; OCR is set, we're using block addressing, so bra MmcIni4 ; skip ahead MmcIni3 bcf M_FLAGS,M_BKADR ;We're dealing with byte, not block addressing movlw 0x50 ;Send command 16 (expect R1-type response) to movwf M_CMDN ; tell the card we want to deal in 512-byte clrf M_ADR3 ; sectors clrf M_ADR2 ; " movlw 0x02 ; " movwf M_ADR1 ; " clrf M_ADR0 ; " bcf M_FLAGS,M_CMDLR ; " bcf M_FLAGS,M_CMDRB ; " call MmcCmd ; " movf M_CMDN,W ;If this command returned any response other btfss STATUS,Z ; than 0x00, something is wrong, fail the init bsf M_FLAGS,M_FAIL ; operation btfsc M_FLAGS,M_FAIL ;If this command failed, something is wrong, return ; fail the init operation MmcIni4 movlw 0x7B ;Send command 59 (expect R1-type response) to movwf M_CMDN ; tell the card we want to make life hard on clrf M_ADR3 ; ourselves and have our CRCs checked by the clrf M_ADR2 ; card clrf M_ADR1 ; " movlw 0x01 ; " movwf M_ADR0 ; " bcf M_FLAGS,M_CMDLR ; " bcf M_FLAGS,M_CMDRB ; " call MmcCmd ; " movf M_CMDN,W ;If this command returned any response other btfss STATUS,Z ; than 0x00, something is wrong, fail the init bsf M_FLAGS,M_FAIL ; operation btfsc M_FLAGS,M_FAIL ;If this command failed, something is wrong, return ; fail the init operation bsf PORTC,RC3 ;Deassert !CS movf M_FLAGS,W ;Set up the card info byte of the status block andlw B'00000111' ; " movwf CARDINF ; " return ;Congratulations, card is initialized! ;Convert a block address to a byte address if byte addressing is in effect. ; Sets M_FAIL if the block address is above 0x7FFFFF (and thus can't fit as a ; byte address). MmcConvAddr bcf M_FLAGS,M_FAIL ;Assume no failure to start with btfsc M_FLAGS,M_BKADR ;If block addressing is in effect, the address return ; does not need to be converted movf M_ADR3,F ;Make sure that the top 9 bits of the block btfss STATUS,Z ; address are clear; if they are not, set the bsf M_FLAGS,M_FAIL ; fail flag btfsc M_ADR2,7 ; " bsf M_FLAGS,M_FAIL ; " btfsc M_FLAGS,M_FAIL ;If the fail flag is set, we're done return ; " lslf M_ADR0,F ;Multiply the block address by 2 and then by rlf M_ADR1,F ; 256 rlf M_ADR2,W ; " movwf M_ADR3 ; " movf M_ADR1,W ; " movwf M_ADR2 ; " movf M_ADR0,W ; " movwf M_ADR1 ; " clrf M_ADR0 ; " return ;Increment the address by one block according to the block/byte addressing ; mode. No protection is provided against the address wrapping around. MmcIncAddr movlw 0x01 ;Add 1 to the address if we're in block mode, btfss M_FLAGS,M_BKADR ; add 512 to the address if we're in byte mode, movlw 0 ; in either case carrying the remainder through addwf M_ADR0,F ; " movlw 0 ; " btfss M_FLAGS,M_BKADR ; " movlw 0x02 ; " addwfc M_ADR1,F ; " movlw 0 ; " addwfc M_ADR2,F ; " addwfc M_ADR3,F ; " return ;Read 512 bytes of data from MMC card into buffer pointed to by FSR0. Sets ; M_FAIL on fail. Trashes TEMP, TEMP2, and FSR0. MmcReadData bcf M_FLAGS,M_FAIL ;Assume no failure to start with movlb 4 ;Switch to the bank with the SSP registers clrf TEMP ;Try 65536 times to get the data token clrf TEMP2 ; " MmcRea1 movlw 0xFF ;Clock a byte out of the MMC card while keeping movwf SSP1BUF ; MOSI high btfss SSP1STAT,BF ; " bra $-1 ; " movf SSP1BUF,W ;If we've received the data token, skip ahead xorlw 0xFE ; " btfsc STATUS,Z ; " bra MmcRea2 ; " decfsz TEMP,F ;If not, decrement the retry count and try bra MmcRea1 ; again decfsz TEMP2,F ; " bra MmcRea1 ; " bsf M_FLAGS,M_FAIL ;If we didn't get the data token after 65536 movlb 0 ; tries, give up and fail the operation return ; " MmcRea2 clrf TEMP ;Read 256 pairs of bytes clrf CRC16H ;Start CRC16 registers at zero clrf CRC16L ; " MmcRea3 movlw 0xFF ;Clock the next data byte out of the MMC card movwf SSP1BUF ; while keeping MOSI high movf TEMP,F ;If this is the first byte, we don't have a btfsc STATUS,Z ; previous byte to CRC, so skip ahead bra MmcRea4 ; " moviw -1[FSR0] ;Update the CRC with the previous byte while xorwf CRC16H,W ; the next one is being received movwf CRC16H ; " movlp high LutCrc16H ; " callw ; " xorwf CRC16L,W ; " xorwf CRC16H,F ; " xorwf CRC16H,W ; " xorwf CRC16H,F ; " movlp high LutCrc16L ; " callw ; " movwf CRC16L ; " MmcRea4 btfss SSP1STAT,BF ;Wait until the next byte is received bra $-1 ; " movf SSP1BUF,W ;Move the byte we clocked out to the buffer and movwi FSR0++ ; increment the pointer movlw 0xFF ;Clock the next data byte out of the MMC card movwf SSP1BUF ; while keeping MOSI high moviw -1[FSR0] ;Update the CRC with the previous byte while xorwf CRC16H,W ; the next one is being received movwf CRC16H ; " movlp high LutCrc16H ; " callw ; " xorwf CRC16L,W ; " xorwf CRC16H,F ; " xorwf CRC16H,W ; " xorwf CRC16H,F ; " movlp high LutCrc16L ; " callw ; " movwf CRC16L ; " btfss SSP1STAT,BF ;Wait until the next byte is received bra $-1 ; " movf SSP1BUF,W ;Move the byte we clocked out to the buffer and movwi FSR0++ ; increment the pointer decfsz TEMP,F ;Decrement the counter and go back to read the bra MmcRea3 ; next byte pair, unless we're done movlw 0xFF ;Clock the high CRC byte out of the MMC card movwf SSP1BUF ; while keeping MOSI high moviw -1[FSR0] ;Update the CRC with the final data byte while xorwf CRC16H,W ; the high CRC byte is being received movwf CRC16H ; " movlp high LutCrc16H ; " callw ; " xorwf CRC16L,W ; " xorwf CRC16H,F ; " xorwf CRC16H,W ; " xorwf CRC16H,F ; " movlp high LutCrc16L ; " callw ; " movwf CRC16L ; " movlp 0 ;Restore PCLATH from all the CRC calculating btfss SSP1STAT,BF ;Wait until the byte is received bra $-1 ; " movf SSP1BUF,W ;If it doesn't match what we calculated, set xorwf CRC16H,W ; the fail flag btfss STATUS,Z ; " bsf M_FLAGS,M_FAIL ; " movlw 0xFF ;Clock the low CRC byte out of the MMC card movwf SSP1BUF ; while keeping MOSI high btfss SSP1STAT,BF ;Wait until the byte is received bra $-1 ; " movf SSP1BUF,W ;If it doesn't match what we calculated, set xorwf CRC16L,W ; the fail flag btfss STATUS,Z ; " bsf M_FLAGS,M_FAIL ; " movlb 0 ;Return to the default bank btfss M_FLAGS,M_FAIL ;If the CRC check didn't fail, return now return ; " call MmcStopOngoing ;If the CRC check did fail, stop any ongoing bsf M_FLAGS,M_FAIL ; read (since the card doesn't know anything's return ; wrong) and then return failure ;Write 512 bytes of data to MMC card from buffer pointed to by FSR0. Sets ; M_FAIL on fail. Trashes TEMP, TEMP2, and FSR0. MmcWriteData bcf M_FLAGS,M_FAIL ;Assume no failure to start with movlb 4 ;Switch to the bank with the SSP registers clrf CRC16H ;Start CRC16 registers at zero clrf CRC16L ; " movlw 0xFF ;Clock a dummy byte while keeping MOSI high movwf SSP1BUF ; " btfss SSP1STAT,BF ; " bra $-1 ; " movlw 0xFE ;Clock the data token into the MMC card (note btfsc M_FLAGS,M_MBWR ; that CMD25, multi-block write, requires a movlw 0xFC ; different token than CMD24, single-block movwf SSP1BUF ; write, so we differentiate based on the flag btfss SSP1STAT,BF ; for ongoing multi-block write) bra $-1 ; " clrf TEMP ;Send 256 pairs of bytes MmcWri0 moviw FSR0++ ;Clock the next data byte into the MMC card movwf SSP1BUF ; " xorwf CRC16H,W ;Update the CRC while the byte is transmitting movwf CRC16H ; " movlp high LutCrc16H ; " callw ; " xorwf CRC16L,W ; " xorwf CRC16H,F ; " xorwf CRC16H,W ; " xorwf CRC16H,F ; " movlp high LutCrc16L ; " callw ; " movwf CRC16L ; " btfss SSP1STAT,BF ;Wait until the byte is done transmitting bra $-1 ; " moviw FSR0++ ;Clock the next data byte into the MMC card movwf SSP1BUF ; " xorwf CRC16H,W ;Update the CRC while the byte is transmitting movwf CRC16H ; " movlp high LutCrc16H ; " callw ; " xorwf CRC16L,W ; " xorwf CRC16H,F ; " xorwf CRC16H,W ; " xorwf CRC16H,F ; " movlp high LutCrc16L ; " callw ; " movwf CRC16L ; " btfss SSP1STAT,BF ;Wait until the byte is done transmitting bra $-1 ; " decfsz TEMP,F ;Decrement the counter and go back to write the bra MmcWri0 ; next byte pair, unless we're done movlp 0 ;Restore PCLATH from all the CRC calculating movf CRC16H,W ;Clock the high CRC byte into the MMC card movwf SSP1BUF ; " btfss SSP1STAT,BF ; " bra $-1 ; " movf CRC16L,W ;Clock the low CRC byte into the MMC card movwf SSP1BUF ; " btfss SSP1STAT,BF ; " bra $-1 ; " movlw 0xFF ;Clock data response byte out of the MMC card movwf SSP1BUF ; while keeping MOSI high btfss SSP1STAT,BF ; " bra $-1 ; " movf SSP1BUF,W ;If the status byte indicates that the write andlw B'00011111' ; was rejected for any reason, fail the write xorlw B'00000101' ; operation btfss STATUS,Z ; " bsf M_FLAGS,M_FAIL ; " btfss M_FLAGS,M_FAIL ;If we didn't fail, wait for the card not to be call MmcWaitBusy ; busy anymore movlb 0 ;Return to the default bank return ;Stop a multiblock read or write, if one is ongoing, and deassert !CS. Sets ; M_FAIL on fail. Trashes TEMP and TEMP2. MmcStopOngoing bcf M_FLAGS,M_FAIL ;Assume no failure to start with btfsc M_FLAGS,M_MBWR ;If there's an ongoing write operation, make it bra MmcSto0 ; stop btfss M_FLAGS,M_MBRD ;If there's not an ongoing read operation, this return ; function was called needlessly, return movlw 0x4C ;Send a CMD12 to stop the ongoing read, R1b movwf M_CMDN ; reply type clrf M_ADR3 ; " clrf M_ADR2 ; " clrf M_ADR1 ; " clrf M_ADR0 ; " bcf M_FLAGS,M_CMDLR ; " bsf M_FLAGS,M_CMDRB ; " call MmcCmd ; " bcf M_FLAGS,M_MBRD ;Clear the ongoing multiblock read flag bsf PORTC,RC3 ;Deassert !CS return MmcSto0 movlb 4 ;Switch to the bank with the SSP registers movlw 0xFD ;Clock the end-of-data token into the MMC card movwf SSP1BUF ; " btfss SSP1STAT,BF ; " bra $-1 ; " movlw 0xFF ;Clock a dummy byte while keeping MOSI high movwf SSP1BUF ; " btfss SSP1STAT,BF ; " bra $-1 ; " call MmcWaitBusy ;Wait for the card to not be busy anymore movlb 0 ;Return to the default bank bcf M_FLAGS,M_MBWR ;Clear the ongoing multiblock write flag bsf PORTC,RC3 ;Deassert !CS return ;Send the command contained in M_BUF1-6 to MMC card. Sets M_FAIL on fail. ; Trashes TEMP. MmcCmd bcf M_FLAGS,M_FAIL ;Assume no failure to start with clrf TEMP ;Start the CRC7 register out at 0 movlp high LutCrc7 ;Point PCLATH to the CRC7 lookup table movlb 4 ;Switch to the bank with the SSP registers movf M_CMDN,W ;Clock out all six MMC buffer bytes as command, movwf SSP1BUF ; calculating the CRC7 along the way xorwf TEMP,W ; " callw ; " movwf TEMP ; " btfss SSP1STAT,BF ; " bra $-1 ; " movf M_ADR3,W ; " movwf SSP1BUF ; " xorwf TEMP,W ; " callw ; " movwf TEMP ; " btfss SSP1STAT,BF ; " bra $-1 ; " movf M_ADR2,W ; " movwf SSP1BUF ; " xorwf TEMP,W ; " callw ; " movwf TEMP ; " btfss SSP1STAT,BF ; " bra $-1 ; " movf M_ADR1,W ; " movwf SSP1BUF ; " xorwf TEMP,W ; " callw ; " movwf TEMP ; " btfss SSP1STAT,BF ; " bra $-1 ; " movf M_ADR0,W ; " movwf SSP1BUF ; " xorwf TEMP,W ; " callw ; " movlp 0 ; " movwf TEMP ; " bsf TEMP,0 ; " btfss SSP1STAT,BF ; " bra $-1 ; " movf TEMP,W ; " movwf SSP1BUF ; " btfss SSP1STAT,BF ; " bra $-1 ; " ;TODO for CMD12, it is necessary to clock and throw away a stuff byte? movlw 8 ;Try to get status as many as eight times movwf TEMP ; " MmcCmd1 movlw 0xFF ;Clock a byte out of the MMC card while keeping movwf SSP1BUF ; MOSI high btfss SSP1STAT,BF ; " bra $-1 ; " incf SSP1BUF,W ;If we read back anything but 0xFF, skip ahead btfss STATUS,Z ; " bra MmcCmd2 ; " decfsz TEMP,F ;Decrement the attempt counter until we've bra MmcCmd1 ; tried eight times; if we haven't gotten a bsf M_FLAGS,M_FAIL ; reply by the eighth attempt, signal failure movlb 0 ; and return return ; " MmcCmd2 decf WREG,W ;Store the byte we received as R1-type status movwf M_CMDN ; in the buffer btfss M_FLAGS,M_CMDLR ;If we aren't expecting a long (R3/R7-type) bra MmcCmd3 ; reply, we're done movlw 0xFF ;Clock first extended reply byte out of the movwf SSP1BUF ; MMC card while keeping MOSI high and store it btfss SSP1STAT,BF ; in the buffer bra $-1 ; " movf SSP1BUF,W ; " movwf M_ADR3 ; " movlw 0xFF ;Clock second extended reply byte out of the movwf SSP1BUF ; MMC card while keeping MOSI high and store it btfss SSP1STAT,BF ; in the buffer bra $-1 ; " movf SSP1BUF,W ; " movwf M_ADR2 ; " movlw 0xFF ;Clock third extended reply byte out of the movwf SSP1BUF ; MMC card while keeping MOSI high and store it btfss SSP1STAT,BF ; in the buffer bra $-1 ; " movf SSP1BUF,W ; " movwf M_ADR1 ; " movlw 0xFF ;Clock fourth extended reply byte out of the movwf SSP1BUF ; MMC card while keeping MOSI high and store it btfss SSP1STAT,BF ; in the buffer bra $-1 ; " movf SSP1BUF,W ; " movwf M_ADR0 ; " MmcCmd3 btfsc M_FLAGS,M_CMDRB ;If we're expecting an R1b reply, wait for the call MmcWaitBusy ; card not to be busy anymore before returning movlb 0 ;Restore BSR to 0 return ;Waits for the card not to be busy anymore. Sets M_FAIL on fail. Trashes TEMP ; and TEMP2. Expects BSR to be 4 and does not set or reset this. MmcWaitBusy clrf TEMP ;Check 65536 times to see if the card is busy clrf TEMP2 ; " MmcWai0 movlw 0xFF ;Clock a byte out of the MMC card while keeping movwf SSP1BUF ; MOSI high btfss SSP1STAT,BF ; " bra $-1 ; " movf SSP1BUF,W ;Check if MISO is still low, if it's not, the btfss STATUS,Z ; card is no longer busy and we can return return ; " decfsz TEMP,F ;If it's not done, try again bra MmcWai0 ; " decfsz TEMP2,F ; " bra MmcWai0 ; " bsf M_FLAGS,M_FAIL ;If out of tries, fail the operation return ;;; Idle Handler ;;; org 0x7F2 NoDevices btfsc PORTA,RA5 ;Spin until our !ENBL goes low bra $-1 ; " bcf PORTA,RA0 ;Assert !ENBL for next device in chain btfss PORTA,RA5 ;Spin until our !ENBL goes high bra $-1 ; " bsf PORTA,RA0 ;Deassert !ENBL for next device in chain bra NoDevices SelectNext movlw B'00110010' ;Tristate RD tris 7 ; " bcf PORTA,RA0 ;Assert !ENBL for next device in chain btfss PORTA,RA5 ;Spin until our !ENBL goes high bra $-1 ; " bsf PORTA,RA0 ;Deassert !ENBL for next device in chain WaitEnbl movlw B'00110010' ;Tristate RD tris 7 ; " bsf PORTC,RC4 ;Latch a 1 on RD for when we drive it bcf FLAGS,DEVSEL1 ;Select device 0 in the flag bits bcf FLAGS,DEVSEL0 ; " btfsc PORTA,RA5 ;Spin until !ENBL goes low bra $-1 ; " movlw B'00100010' ;Drive the RD pin, high at first tris 7 ; " Dev0Jump decf PORTA,W ;32 entries in the jump table, each has two brw ; instructions; jump to the one matching state Dev0Ph0 bsf PORTC,RC4 ;HOFF is asserted but there's nothing to hold bra Dev0Jump ; off from, so drive RD high to deassert !HSHK Dev0Ph1 bsf PORTC,RC4 ;Mac wants to exchange data for some reason, so bra Dev0Jump ; drive RD high because what else can we do Dev0Ph2 bsf PORTC,RC4 ;Mac wants us to idle, cool, we're already bra Dev0Jump ; idling, so drive RD high to deassert !HSHK Dev0Ph3 call GetCommand ;Mac wants to send a command, this is the only bra Dev0Jump ; way to escape the idle loop Dev0Ph4 bsf PORTC,RC4 ;Mac wants us to reset, this is sorta reset, so bra Dev0Jump ; drive RD high to deassert !HSHK Dev0Ph5 bcf PORTC,RC4 ;Mac wants us to drive RD low, so drive RD low bra Dev0Jump ; " Dev0Ph6 bsf PORTC,RC4 ;Mac wants us to drive RD high, so drive RD bra Dev0Jump ; high Dev0Ph7 bsf PORTC,RC4 ;Mac wants us to drive RD high, so drive RD bra Dev0Jump ; high Dev0Ph8 bsf PORTC,RC4 ;Mac wants to talk to next device bra EnterDev1 ; " Dev0Ph9 bsf PORTC,RC4 ;Mac wants to talk to next device bra EnterDev1 ; " Dev0PhA bsf PORTC,RC4 ;Mac wants to talk to next device bra EnterDev1 ; " Dev0PhB bsf PORTC,RC4 ;Mac wants to talk to next device bra EnterDev1 ; " Dev0PhC bsf PORTC,RC4 ;Mac wants to talk to next device bra EnterDev1 ; " Dev0PhD bsf PORTC,RC4 ;Mac wants to talk to next device bra EnterDev1 ; " Dev0PhE bsf PORTC,RC4 ;Mac wants to talk to next device bra EnterDev1 ; " Dev0PhF bsf PORTC,RC4 ;Mac wants to talk to next device bra EnterDev1 ; " Dev0NEn goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again EnterDev1 btfss DV1FLAG,DV_EXST ;If there is no device 1, select the next goto SelectNext ; device and wait for !ENBL to be deasserted bcf FLAGS,DEVSEL1 ;Select device 1 in the flag bits bsf FLAGS,DEVSEL0 ; " Dev1SelJump decf PORTA,W ;32 entries in the jump table, each has two brw ; instructions; jump to the one matching state Dv1SPh0 bsf PORTC,RC4 ;HOFF is asserted but there's nothing to hold bra Dev1Jump ; off from, so drive RD high to deassert !HSHK Dv1SPh1 bsf PORTC,RC4 ;Mac wants to exchange data for some reason, so bra Dev1Jump ; drive RD high because what else can we do Dv1SPh2 bsf PORTC,RC4 ;Mac wants us to idle, cool, we're already bra Dev1Jump ; idling, so drive RD high to deassert !HSHK Dv1SPh3 call GetCommand ;Mac wants to send a command, this is the only bra Dev1Jump ; way to escape the idle loop Dv1SPh4 bsf PORTC,RC4 ;Mac wants us to reset, this is sorta reset, so bra Dev1Jump ; drive RD high to deassert !HSHK Dv1SPh5 bcf PORTC,RC4 ;Mac wants us to drive RD low, so drive RD low bra Dev1Jump ; " Dv1SPh6 bsf PORTC,RC4 ;Mac wants us to drive RD high, so drive RD bra Dev1Jump ; high Dv1SPh7 bsf PORTC,RC4 ;Mac wants us to drive RD high, so drive RD bra Dev1Jump ; high Dv1SPh8 bsf PORTC,RC4 ;HOFF is asserted but there's nothing to hold bra Dev1SelJump ; off from, so drive RD high to deassert !HSHK Dv1SPh9 bsf PORTC,RC4 ;Mac wants to exchange data for some reason, so bra Dev1SelJump ; drive RD high because what else can we do Dv1SPhA bsf PORTC,RC4 ;Mac wants us to idle, cool, we're already bra Dev1SelJump ; idling, so drive RD high to deassert !HSHK Dv1SPhB call GetCommand ;Mac wants to send a command, this is the only bra Dev1SelJump ; way to escape the idle loop Dv1SPhC bsf PORTC,RC4 ;Mac wants us to reset, this is sorta reset, so bra Dev1SelJump ; drive RD high to deassert !HSHK Dv1SPhD bcf PORTC,RC4 ;Mac wants us to drive RD low, so drive RD low bra Dev1SelJump ; " Dv1SPhE bsf PORTC,RC4 ;Mac wants us to drive RD high, so drive RD bra Dev1SelJump ; high Dv1SPhF bsf PORTC,RC4 ;Mac wants us to drive RD high, so drive RD bra Dev1SelJump ; high Dv1SNEn goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again Dev1Jump decf PORTA,W ;32 entries in the jump table, each has two brw ; instructions; jump to the one matching state Dev1Ph0 bsf PORTC,RC4 ;HOFF is asserted but there's nothing to hold bra Dev1Jump ; off from, so drive RD high to deassert !HSHK Dev1Ph1 bsf PORTC,RC4 ;Mac wants to exchange data for some reason, so bra Dev1Jump ; drive RD high because what else can we do Dev1Ph2 bsf PORTC,RC4 ;Mac wants us to idle, cool, we're already bra Dev1Jump ; idling, so drive RD high to deassert !HSHK Dev1Ph3 call GetCommand ;Mac wants to send a command, this is the only bra Dev1Jump ; way to escape the idle loop Dev1Ph4 bsf PORTC,RC4 ;Mac wants us to reset, this is sorta reset, so bra Dev1Jump ; drive RD high to deassert !HSHK Dev1Ph5 bcf PORTC,RC4 ;Mac wants us to drive RD low, so drive RD low bra Dev1Jump ; " Dev1Ph6 bsf PORTC,RC4 ;Mac wants us to drive RD high, so drive RD bra Dev1Jump ; high Dev1Ph7 bsf PORTC,RC4 ;Mac wants us to drive RD high, so drive RD bra Dev1Jump ; high Dev1Ph8 bsf PORTC,RC4 ;Mac wants to talk to next device bra EnterDev2 ; " Dev1Ph9 bsf PORTC,RC4 ;Mac wants to talk to next device bra EnterDev2 ; " Dev1PhA bsf PORTC,RC4 ;Mac wants to talk to next device bra EnterDev2 ; " Dev1PhB bsf PORTC,RC4 ;Mac wants to talk to next device bra EnterDev2 ; " Dev1PhC bsf PORTC,RC4 ;Mac wants to talk to next device bra EnterDev2 ; " Dev1PhD bsf PORTC,RC4 ;Mac wants to talk to next device bra EnterDev2 ; " Dev1PhE bsf PORTC,RC4 ;Mac wants to talk to next device bra EnterDev2 ; " Dev1PhF bsf PORTC,RC4 ;Mac wants to talk to next device bra EnterDev2 ; " Dev1NEn goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again EnterDev2 btfss DV2FLAG,DV_EXST ;If there is no device 2, select the next goto SelectNext ; device and wait for !ENBL to be deasserted bsf FLAGS,DEVSEL1 ;Select device 2 in the flag bits bcf FLAGS,DEVSEL0 ; " Dev2SelJump decf PORTA,W ;32 entries in the jump table, each has two brw ; instructions; jump to the one matching state Dv2SPh0 bsf PORTC,RC4 ;HOFF is asserted but there's nothing to hold bra Dev2Jump ; off from, so drive RD high to deassert !HSHK Dv2SPh1 bsf PORTC,RC4 ;Mac wants to exchange data for some reason, so bra Dev2Jump ; drive RD high because what else can we do Dv2SPh2 bsf PORTC,RC4 ;Mac wants us to idle, cool, we're already bra Dev2Jump ; idling, so drive RD high to deassert !HSHK Dv2SPh3 call GetCommand ;Mac wants to send a command, this is the only bra Dev2Jump ; way to escape the idle loop Dv2SPh4 bsf PORTC,RC4 ;Mac wants us to reset, this is sorta reset, so bra Dev2Jump ; drive RD high to deassert !HSHK Dv2SPh5 bcf PORTC,RC4 ;Mac wants us to drive RD low, so drive RD low bra Dev2Jump ; " Dv2SPh6 bsf PORTC,RC4 ;Mac wants us to drive RD high, so drive RD bra Dev2Jump ; high Dv2SPh7 bsf PORTC,RC4 ;Mac wants us to drive RD high, so drive RD bra Dev2Jump ; high Dv2SPh8 bsf PORTC,RC4 ;HOFF is asserted but there's nothing to hold bra Dev2SelJump ; off from, so drive RD high to deassert !HSHK Dv2SPh9 bsf PORTC,RC4 ;Mac wants to exchange data for some reason, so bra Dev2SelJump ; drive RD high because what else can we do Dv2SPhA bsf PORTC,RC4 ;Mac wants us to idle, cool, we're already bra Dev2SelJump ; idling, so drive RD high to deassert !HSHK Dv2SPhB call GetCommand ;Mac wants to send a command, this is the only bra Dev2SelJump ; way to escape the idle loop Dv2SPhC bsf PORTC,RC4 ;Mac wants us to reset, this is sorta reset, so bra Dev2SelJump ; drive RD high to deassert !HSHK Dv2SPhD bcf PORTC,RC4 ;Mac wants us to drive RD low, so drive RD low bra Dev2SelJump ; " Dv2SPhE bsf PORTC,RC4 ;Mac wants us to drive RD high, so drive RD bra Dev2SelJump ; high Dv2SPhF bsf PORTC,RC4 ;Mac wants us to drive RD high, so drive RD bra Dev2SelJump ; high Dv2SNEn goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again Dev2Jump decf PORTA,W ;32 entries in the jump table, each has two brw ; instructions; jump to the one matching state Dev2Ph0 bsf PORTC,RC4 ;HOFF is asserted but there's nothing to hold bra Dev2Jump ; off from, so drive RD high to deassert !HSHK Dev2Ph1 bsf PORTC,RC4 ;Mac wants to exchange data for some reason, so bra Dev2Jump ; drive RD high because what else can we do Dev2Ph2 bsf PORTC,RC4 ;Mac wants us to idle, cool, we're already bra Dev2Jump ; idling, so drive RD high to deassert !HSHK Dev2Ph3 call GetCommand ;Mac wants to send a command, this is the only bra Dev2Jump ; way to escape the idle loop Dev2Ph4 bsf PORTC,RC4 ;Mac wants us to reset, this is sorta reset, so bra Dev2Jump ; drive RD high to deassert !HSHK Dev2Ph5 bcf PORTC,RC4 ;Mac wants us to drive RD low, so drive RD low bra Dev2Jump ; " Dev2Ph6 bsf PORTC,RC4 ;Mac wants us to drive RD high, so drive RD bra Dev2Jump ; high Dev2Ph7 bsf PORTC,RC4 ;Mac wants us to drive RD high, so drive RD bra Dev2Jump ; high Dev2Ph8 bsf PORTC,RC4 ;Mac wants to talk to next device bra EnterDev3 ; " Dev2Ph9 bsf PORTC,RC4 ;Mac wants to talk to next device bra EnterDev3 ; " Dev2PhA bsf PORTC,RC4 ;Mac wants to talk to next device bra EnterDev3 ; " Dev2PhB bsf PORTC,RC4 ;Mac wants to talk to next device bra EnterDev3 ; " Dev2PhC bsf PORTC,RC4 ;Mac wants to talk to next device bra EnterDev3 ; " Dev2PhD bsf PORTC,RC4 ;Mac wants to talk to next device bra EnterDev3 ; " Dev2PhE bsf PORTC,RC4 ;Mac wants to talk to next device bra EnterDev3 ; " Dev2PhF bsf PORTC,RC4 ;Mac wants to talk to next device bra EnterDev3 ; " Dev2NEn goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again EnterDev3 btfss DV3FLAG,DV_EXST ;If there is no device 3, select the next goto SelectNext ; device and wait for !ENBL to be deasserted bsf FLAGS,DEVSEL1 ;Select device 3 in the flag bits bsf FLAGS,DEVSEL0 ; " Dev3SelJump decf PORTA,W ;32 entries in the jump table, each has two brw ; instructions; jump to the one matching state Dv3SPh0 bsf PORTC,RC4 ;HOFF is asserted but there's nothing to hold bra Dev3Jump ; off from, so drive RD high to deassert !HSHK Dv3SPh1 bsf PORTC,RC4 ;Mac wants to exchange data for some reason, so bra Dev3Jump ; drive RD high because what else can we do Dv3SPh2 bsf PORTC,RC4 ;Mac wants us to idle, cool, we're already bra Dev3Jump ; idling, so drive RD high to deassert !HSHK Dv3SPh3 call GetCommand ;Mac wants to send a command, this is the only bra Dev3Jump ; way to escape the idle loop Dv3SPh4 bsf PORTC,RC4 ;Mac wants us to reset, this is sorta reset, so bra Dev3Jump ; drive RD high to deassert !HSHK Dv3SPh5 bcf PORTC,RC4 ;Mac wants us to drive RD low, so drive RD low bra Dev3Jump ; " Dv3SPh6 bsf PORTC,RC4 ;Mac wants us to drive RD high, so drive RD bra Dev3Jump ; high Dv3SPh7 bsf PORTC,RC4 ;Mac wants us to drive RD high, so drive RD bra Dev3Jump ; high Dv3SPh8 bsf PORTC,RC4 ;HOFF is asserted but there's nothing to hold bra Dev3SelJump ; off from, so drive RD high to deassert !HSHK Dv3SPh9 bsf PORTC,RC4 ;Mac wants to exchange data for some reason, so bra Dev3SelJump ; drive RD high because what else can we do Dv3SPhA bsf PORTC,RC4 ;Mac wants us to idle, cool, we're already bra Dev3SelJump ; idling, so drive RD high to deassert !HSHK Dv3SPhB call GetCommand ;Mac wants to send a command, this is the only bra Dev3SelJump ; way to escape the idle loop Dv3SPhC bsf PORTC,RC4 ;Mac wants us to reset, this is sorta reset, so bra Dev3SelJump ; drive RD high to deassert !HSHK Dv3SPhD bcf PORTC,RC4 ;Mac wants us to drive RD low, so drive RD low bra Dev3SelJump ; " Dv3SPhE bsf PORTC,RC4 ;Mac wants us to drive RD high, so drive RD bra Dev3SelJump ; high Dv3SPhF bsf PORTC,RC4 ;Mac wants us to drive RD high, so drive RD bra Dev3SelJump ; high Dv3SNEn goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again Dev3Jump decf PORTA,W ;32 entries in the jump table, each has two brw ; instructions; jump to the one matching state Dev3Ph0 bsf PORTC,RC4 ;HOFF is asserted but there's nothing to hold bra Dev3Jump ; off from, so drive RD high to deassert !HSHK Dev3Ph1 bsf PORTC,RC4 ;Mac wants to exchange data for some reason, so bra Dev3Jump ; drive RD high because what else can we do Dev3Ph2 bsf PORTC,RC4 ;Mac wants us to idle, cool, we're already bra Dev3Jump ; idling, so drive RD high to deassert !HSHK Dev3Ph3 call GetCommand ;Mac wants to send a command, this is the only bra Dev3Jump ; way to escape the idle loop Dev3Ph4 bsf PORTC,RC4 ;Mac wants us to reset, this is sorta reset, so bra Dev3Jump ; drive RD high to deassert !HSHK Dev3Ph5 bcf PORTC,RC4 ;Mac wants us to drive RD low, so drive RD low bra Dev3Jump ; " Dev3Ph6 bsf PORTC,RC4 ;Mac wants us to drive RD high, so drive RD bra Dev3Jump ; high Dev3Ph7 bsf PORTC,RC4 ;Mac wants us to drive RD high, so drive RD bra Dev3Jump ; high Dev3Ph8 bsf PORTC,RC4 ;Mac wants to talk to next device, we have none goto SelectNext ; so select the next and await !ENBL deasserted Dev3Ph9 bsf PORTC,RC4 ;Mac wants to talk to next device, we have none goto SelectNext ; so select the next and await !ENBL deasserted Dev3PhA bsf PORTC,RC4 ;Mac wants to talk to next device, we have none goto SelectNext ; so select the next and await !ENBL deasserted Dev3PhB bsf PORTC,RC4 ;Mac wants to talk to next device, we have none goto SelectNext ; so select the next and await !ENBL deasserted Dev3PhC bsf PORTC,RC4 ;Mac wants to talk to next device, we have none goto SelectNext ; so select the next and await !ENBL deasserted Dev3PhD bsf PORTC,RC4 ;Mac wants to talk to next device, we have none goto SelectNext ; so select the next and await !ENBL deasserted Dev3PhE bsf PORTC,RC4 ;Mac wants to talk to next device, we have none goto SelectNext ; so select the next and await !ENBL deasserted Dev3PhF bsf PORTC,RC4 ;Mac wants to talk to next device, we have none goto SelectNext ; so select the next and await !ENBL deasserted Dev3NEn goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again goto WaitEnbl ;!ENBL has been deasserted, so get off the bus nop ; and wait for it to be asserted again ;;; Icon ;;; org 0xF00 Icon retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x03 retlw 0xFE retlw 0xE0 retlw 0x00 retlw 0x0E retlw 0x07 retlw 0xB0 retlw 0x00 retlw 0x18 retlw 0x00 retlw 0x70 retlw 0x00 retlw 0x33 retlw 0x40 retlw 0xF0 retlw 0x00 retlw 0x2E retlw 0xDB retlw 0xE0 retlw 0x00 retlw 0x3C retlw 0x9B retlw 0xC0 retlw 0x00 retlw 0x1D retlw 0x9B retlw 0x00 retlw 0x00 retlw 0x09 retlw 0x9B retlw 0x00 retlw 0x00 retlw 0x09 retlw 0x9B retlw 0x00 retlw 0x00 retlw 0x08 retlw 0x9B retlw 0x00 retlw 0x00 retlw 0x08 retlw 0xBB retlw 0xE0 retlw 0x00 retlw 0x0C retlw 0x7B retlw 0xB0 retlw 0x7F retlw 0xFC retlw 0x3A retlw 0x7E retlw 0x80 retlw 0x06 retlw 0x00 retlw 0xF1 retlw 0x80 retlw 0x07 retlw 0x83 retlw 0xE1 retlw 0x80 retlw 0x03 retlw 0xFF retlw 0xC1 retlw 0x80 retlw 0x00 retlw 0xFF retlw 0x01 retlw 0x80 retlw 0x00 retlw 0x00 retlw 0x01 retlw 0x8C retlw 0x00 retlw 0x00 retlw 0x01 retlw 0x80 retlw 0x00 retlw 0x00 retlw 0x01 retlw 0x80 retlw 0x00 retlw 0x00 retlw 0x01 retlw 0x7F retlw 0xFF retlw 0xFF retlw 0xFE retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x00 retlw 0x03 retlw 0xFE retlw 0xE0 retlw 0x00 retlw 0x0F retlw 0xFF retlw 0xF0 retlw 0x00 retlw 0x1F retlw 0xFF retlw 0xF0 retlw 0x00 retlw 0x3F retlw 0xFF retlw 0xF0 retlw 0x00 retlw 0x3F retlw 0xFF retlw 0xE0 retlw 0x00 retlw 0x3F retlw 0xFF retlw 0xC0 retlw 0x00 retlw 0x1F retlw 0xFF retlw 0x00 retlw 0x00 retlw 0x0F retlw 0xFF retlw 0x00 retlw 0x00 retlw 0x0F retlw 0xFF retlw 0x00 retlw 0x00 retlw 0x0F retlw 0xFF retlw 0x00 retlw 0x00 retlw 0x0F retlw 0xFF retlw 0xE0 retlw 0x00 retlw 0x0F retlw 0xFF retlw 0xF0 retlw 0x7F retlw 0xFF retlw 0xFF retlw 0xFE retlw 0xFF retlw 0xFF retlw 0xFF retlw 0xFF retlw 0xFF retlw 0xFF retlw 0xFF retlw 0xFF retlw 0xFF retlw 0xFF retlw 0xFF retlw 0xFF retlw 0xFF retlw 0xFF retlw 0xFF retlw 0xFF retlw 0xFF retlw 0xFF retlw 0xFF retlw 0xFF retlw 0xFF retlw 0xFF retlw 0xFF retlw 0xFF retlw 0xFF retlw 0xFF retlw 0xFF retlw 0xFF retlw 0xFF retlw 0xFF retlw 0xFF retlw 0xFF retlw 0x7F retlw 0xFF retlw 0xFF retlw 0xFE ;;; Transmitter Code ;;; org 0x1000 ;Transmits GROUPS 7-byte groups of non-encoded data from the data buffer. Sets ; ABORTED if a phase change caused the command to be aborted, in which case ; caller should return to idle state as soon as possible. Trashes FSR0, TEMP, ; TEMP2, and GROUPS. Transmit movlb 0 ;Point BSR to 0 so we can access PORTA/PORTC movlw 0x20 ;Point FSR0 at the top of the data buffer movwf FSR0H ; " movlw 0x48 ; " movwf FSR0L ; " bcf FLAGS,ABORTED ;Clear aborted flag to start decf PORTA,W ;Check the current state xorlw B'00000100' ;If it's 2, then mac is ready for us to request btfss STATUS,Z ; to send; if it's anything else, signal an bra XAbort ; abort to get us to the idle jump table ASAP bcf PORTC,RC4 ;Assert !HSHK to request to send Transm0 decf PORTA,W ;Check the current state xorlw B'00000100' ;If we're still in state 2, keep checking btfsc STATUS,Z ; " bra Transm0 ; " xorlw B'00000010' ;If we're in state 3, most likely mac is about btfsc STATUS,Z ; to change to state 1, so keep checking bra Transm0 ; " xorlw B'00000100' ;If we're in state 1, get ready to send; if any btfss STATUS,Z ; other state, we can't handle it, so signal an bra XAbort ; abort to get us to the idle jump table ASAP ;fall through Transmitter movlw 128 ;Set up fractional delay counter (see below) movwf TEMP ; " clrf TEMP2 ;Clear counter for sync byte loop movlp high XFromBuffer;Select from-buffer as transmit loop bsf PORTC,RC4 ;Raise RD and then delay long enough to make DELAY 55 ; sure that IWM is awaiting an MSB XSyncByteLoop incf TEMP2,F ;-2 Increment the sync bit counter; if it's btfsc TEMP2,0 ;-1 odd, falling edge on RD to send a 1 bit; bcf PORTC,RC4 ; 0 this way we send 0xAA as a sync byte movlw 87 ;+1 (*1) Reckon the delay to slow this from a addwf TEMP,F ;+2 2 us data cell to a 96/47 us data cell as btfsc STATUS,C ;+3 16 cycles plus 16/47 of a cycle, which is bra $+1 ;+4 approximated here as 87/256 of a cycle, bsf PORTC,RC4 ;+5 and raise RD for the next falling edge decf PORTA,W ;+6 (*2) Check the current state; if it is 0 andlw B'00111100' ;+7 (holdoff) or 1 (communication), continue btfss STATUS,Z ;-8 transmitting; else, abort and get us back goto XAbort ;-7 to idle loop ASAP movlw 0x40 ;-6 If we've more sync bits to send, loop for btfss TEMP2,3 ;-5 the next, else set LSBs register for the bra XSyncByteLoop ;-4(-3) group we're about to send and jump movwf TEMP2 ;-3 into the appropriate send loop clrf PCL ;-2 -1 " XFinished decf PORTA,W ;Check the current state xorlw B'00000010' ;If it's still 1 (communication), mac hasn't btfsc STATUS,Z ; realized we're done transmitting yet, so loop bra XFinished ; " xorlw B'00000100' ;If it's 3 (request send), mac is probably btfsc STATUS,Z ; transitioning through on its way to 2, so bra XFinished ; loop xorlw B'00000010' ;If it's anything but 2 (idle), set the flag btfss STATUS,Z ; for an aborted command to let the caller know bsf FLAGS,ABORTED ; that something weird's going on movlp 0 ;Reset PCLATH to where we're returning return XSuspend decf GROUPS,F ;We finished a group, so decrement group count XSuspe0 decf PORTA,W ;Check the current state btfsc STATUS,Z ;If it's 0 (holdoff), mac is still asking us to bra XSuspe0 ; hold off, so loop again xorlw B'00000010' ;If it's anything else but 1 (communication), btfss STATUS,Z ; either mac wants to abort the command or bra XAbort ; something weird's going on, so abort movf GROUPS,F ;If mac asked us to suspend during the last btfsc STATUS,Z ; group, we resume by being finished and bra XFinished ; waiting to go to state 2 (idle) clrf TEMP2 ;Clear counter for sync byte loop goto XSyncByteLoop ;Resume transmission after interrupted group XAbort bsf PORTC,RC4 ;Deassert !HSHK if it was asserted bsf FLAGS,ABORTED ;Raise the aborted flag movlp 0 ;Reset PCLATH to where we're returning return org 0x1100 XFromBuffer bcf PORTC,RC4 ; 0 Start 7-to-8-encoded group; MSB always set movlw 87 ;+1 (*1) addwf TEMP,F ;+2 " btfsc STATUS,C ;+3 " bra $+1 ;+4 " bsf PORTC,RC4 ;+5 " decf PORTA,W ;+6 (*2) andlw B'00111100' ;+7 " btfss STATUS,Z ;-8 " goto XAbort ;-7 " decf PORTA,W ;-6 (*2) andlw B'00111100' ;-5 " btfss STATUS,Z ;-4 " goto XAbort ;-3 " nop ;-2 btfsc INDF0,7 ;-1 Falling edge on RD if bit 7 of this byte is bcf PORTC,RC4 ; 0 set movlw 87 ;+1 (*1) addwf TEMP,F ;+2 " btfsc STATUS,C ;+3 " bra $+1 ;+4 " bsf PORTC,RC4 ;+5 " decf PORTA,W ;+6 (*2) andlw B'00111100' ;+7 " btfss STATUS,Z ;-8 " goto XAbort ;-7 " decf PORTA,W ;-6 (*2) andlw B'00111100' ;-5 " btfss STATUS,Z ;-4 " goto XAbort ;-3 " nop ;-2 btfsc INDF0,6 ;-1 Falling edge on RD if bit 6 of this byte is bcf PORTC,RC4 ; 0 set movlw 87 ;+1 (*1) addwf TEMP,F ;+2 " btfsc STATUS,C ;+3 " bra $+1 ;+4 " bsf PORTC,RC4 ;+5 " decf PORTA,W ;+6 (*2) andlw B'00111100' ;+7 " btfss STATUS,Z ;-8 " goto XAbort ;-7 " decf PORTA,W ;-6 (*2) andlw B'00111100' ;-5 " btfss STATUS,Z ;-4 " goto XAbort ;-3 " nop ;-2 btfsc INDF0,5 ;-1 Falling edge on RD if bit 5 of this byte is bcf PORTC,RC4 ; 0 set movlw 87 ;+1 (*1) addwf TEMP,F ;+2 " btfsc STATUS,C ;+3 " bra $+1 ;+4 " bsf PORTC,RC4 ;+5 " decf PORTA,W ;+6 (*2) andlw B'00111100' ;+7 " btfss STATUS,Z ;-8 " goto XAbort ;-7 " decf PORTA,W ;-6 (*2) andlw B'00111100' ;-5 " btfss STATUS,Z ;-4 " goto XAbort ;-3 " nop ;-2 btfsc INDF0,4 ;-1 Falling edge on RD if bit 4 of this byte is bcf PORTC,RC4 ; 0 set movlw 87 ;+1 (*1) addwf TEMP,F ;+2 " btfsc STATUS,C ;+3 " bra $+1 ;+4 " bsf PORTC,RC4 ;+5 " decf PORTA,W ;+6 (*2) andlw B'00111100' ;+7 " btfss STATUS,Z ;-8 " goto XAbort ;-7 " decf PORTA,W ;-6 (*2) andlw B'00111100' ;-5 " btfss STATUS,Z ;-4 " goto XAbort ;-3 " nop ;-2 btfsc INDF0,3 ;-1 Falling edge on RD if bit 3 of this byte is bcf PORTC,RC4 ; 0 set movlw 87 ;+1 (*1) addwf TEMP,F ;+2 " btfsc STATUS,C ;+3 " bra $+1 ;+4 " bsf PORTC,RC4 ;+5 " decf PORTA,W ;+6 (*2) andlw B'00111100' ;+7 " btfss STATUS,Z ;-8 " goto XAbort ;-7 " decf PORTA,W ;-6 (*2) andlw B'00111100' ;-5 " btfss STATUS,Z ;-4 " goto XAbort ;-3 " nop ;-2 btfsc INDF0,2 ;-1 Falling edge on RD if bit 2 of this byte is bcf PORTC,RC4 ; 0 set movlw 87 ;+1 (*1) addwf TEMP,F ;+2 " btfsc STATUS,C ;+3 " bra $+1 ;+4 " bsf PORTC,RC4 ;+5 " decf PORTA,W ;+6 (*2) andlw B'00111100' ;+7 " btfss STATUS,Z ;-8 " goto XAbort ;-7 " decf PORTA,W ;-6 (*2) andlw B'00111100' ;-5 " btfss STATUS,Z ;-4 " goto XAbort ;-3 " nop ;-2 btfsc INDF0,1 ;-1 Falling edge on RD if bit 1 of this byte is bcf PORTC,RC4 ; 0 set movlw 87 ;+1 (*1) addwf TEMP,F ;+2 " btfsc STATUS,C ;+3 " bra $+1 ;+4 " bsf PORTC,RC4 ;+5 " btfsc INDF0,0 ;+6 Copy the LSB of this byte into the LSB bsf TEMP2,7 ;+7 register addfsr FSR0,1 ;-8 Increment pointer to transmit next byte nop ;-7 nop ;-6 nop ;-5 lsrf TEMP2,F ;-4 Shift the LSB register right by one; if a btfss STATUS,C ;-3 one falls out, it's time to send the clrf PCL ;-2(-1) LSBs, otherwise loop again nop ;-1 bcf PORTC,RC4 ; 0 Start of LSB IWM byte; MSB always set movlw 87 ;+1 (*1) addwf TEMP,F ;+2 " btfsc STATUS,C ;+3 " bra $+1 ;+4 " bsf PORTC,RC4 ;+5 " decf PORTA,W ;+6 (*2) andlw B'00111100' ;+7 " btfss STATUS,Z ;-8 " goto XAbort ;-7 " decf PORTA,W ;-6 (*2) andlw B'00111100' ;-5 " btfss STATUS,Z ;-4 " goto XAbort ;-3 " nop ;-2 btfsc TEMP2,6 ;-1 Falling edge on RD if the 7th byte's LSB bcf PORTC,RC4 ; 0 was high movlw 87 ;+1 (*1) addwf TEMP,F ;+2 " btfsc STATUS,C ;+3 " bra $+1 ;+4 " bsf PORTC,RC4 ;+5 " decf PORTA,W ;+6 (*2) andlw B'00111100' ;+7 " btfss STATUS,Z ;-8 " goto XAbort ;-7 " decf PORTA,W ;-6 (*2) andlw B'00111100' ;-5 " btfss STATUS,Z ;-4 " goto XAbort ;-3 " nop ;-2 btfsc TEMP2,5 ;-1 Falling edge on RD if the 6th byte's LSB bcf PORTC,RC4 ; 0 was high movlw 87 ;+1 (*1) addwf TEMP,F ;+2 " btfsc STATUS,C ;+3 " bra $+1 ;+4 " bsf PORTC,RC4 ;+5 " decf PORTA,W ;+6 (*2) andlw B'00111100' ;+7 " btfss STATUS,Z ;-8 " goto XAbort ;-7 " decf PORTA,W ;-6 (*2) andlw B'00111100' ;-5 " btfss STATUS,Z ;-4 " goto XAbort ;-3 " nop ;-2 btfsc TEMP2,4 ;-1 Falling edge on RD if the 5th byte's LSB bcf PORTC,RC4 ; 0 was high movlw 87 ;+1 (*1) addwf TEMP,F ;+2 " btfsc STATUS,C ;+3 " bra $+1 ;+4 " bsf PORTC,RC4 ;+5 " decf PORTA,W ;+6 (*2) andlw B'00111100' ;+7 " btfss STATUS,Z ;-8 " goto XAbort ;-7 " decf PORTA,W ;-6 (*2) andlw B'00111100' ;-5 " btfss STATUS,Z ;-4 " goto XAbort ;-3 " nop ;-2 btfsc TEMP2,3 ;-1 Falling edge on RD if the 4th byte's LSB bcf PORTC,RC4 ; 0 was high movlw 87 ;+1 (*1) addwf TEMP,F ;+2 " btfsc STATUS,C ;+3 " bra $+1 ;+4 " bsf PORTC,RC4 ;+5 " decf PORTA,W ;+6 (*2) andlw B'00111100' ;+7 " btfss STATUS,Z ;-8 " goto XAbort ;-7 " decf PORTA,W ;-6 (*2) andlw B'00111100' ;-5 " btfss STATUS,Z ;-4 " goto XAbort ;-3 " nop ;-2 btfsc TEMP2,2 ;-1 Falling edge on RD if the 3rd byte's LSB bcf PORTC,RC4 ; 0 was high movlw 87 ;+1 (*1) addwf TEMP,F ;+2 " btfsc STATUS,C ;+3 " bra $+1 ;+4 " bsf PORTC,RC4 ;+5 " decf PORTA,W ;+6 (*2) andlw B'00111100' ;+7 " btfss STATUS,Z ;-8 " goto XAbort ;-7 " decf PORTA,W ;-6 (*2) andlw B'00111100' ;-5 " btfss STATUS,Z ;-4 " goto XAbort ;-3 " nop ;-2 btfsc TEMP2,1 ;-1 Falling edge on RD if the 2nd byte's LSB bcf PORTC,RC4 ; 0 was high movlw 87 ;+1 (*1) addwf TEMP,F ;+2 " btfsc STATUS,C ;+3 " bra $+1 ;+4 " bsf PORTC,RC4 ;+5 " decf PORTA,W ;+6 (*2) andlw B'00111100' ;+7 " btfss STATUS,Z ;-8 " goto XAbort ;-7 " decf PORTA,W ;-6 (*2) andlw B'00111100' ;-5 " btfss STATUS,Z ;-4 " goto XAbort ;-3 " nop ;-2 btfsc TEMP2,0 ;-1 Falling edge on RD if the 1st byte's LSB bcf PORTC,RC4 ; 0 was high movlw 87 ;+1 (*1) addwf TEMP,F ;+2 " btfsc STATUS,C ;+3 " bra $+1 ;+4 " bsf PORTC,RC4 ;+5 " movlw 0x40 ;+6 Reset the LSBs register for the next movwf TEMP2 ;+7 group, if there is one decf PORTA,W ;-8 Check the current state btfsc STATUS,Z ;-7 If it's 0 (holdoff), then effect a suspend goto XSuspend ;-6 now that we're done transmitting a group nop ;-5 nop ;-4 decfsz GROUPS,F ;-3 We finished a group, decrement group count; clrf PCL ;-2(-1) if there are more, loop again, goto XFinished ;-1 otherwise we're finished transmitting ;;; Receiver Code ;;; org 0x1800 RecvAbort bsf PORTC,RC4 ;Deassert !HSHK if it was asserted bsf FLAGS,ABORTED ;Raise the aborted flag movlp 0 ;Reset PCLATH to where we're returning return ;Receives data from the mac. Sets ABORTED if a phase change caused the command ; to be aborted, in which case caller should return to idle state as soon as ; possible. Overwrites data buffer with received data in the following way: ; first byte is sync byte, second byte is 0x80 + number of groups in command ; according to mac, third byte is 0x80 + number of groups in anticipated ; response, followed by a string of GROUPS seven-byte decoded groups. Trashes ; FSR0, FSR1, TEMP, and TEMP2. Receive movlb 0 ;Point BSR to 0 so we can access PORTA/PORTC bcf FLAGS,ABORTED ;Clear aborted flag to start movlw 0x20 ;Point FSR0 at the top of the data buffer movwf FSR0H ; " movlw 0x48 ; " movwf FSR0L ; " clrf GROUPS ;Clear counter of total received groups Receiv0 decf PORTA,W ;Check the current state xorlw B'00000100' ;If it's 2, then mac hasn't said it's ready to btfsc STATUS,Z ; send yet, keep waiting bra Receiv0 ; " xorlw B'00000010' ;If it's 3, mac has said it's ready to send, btfss STATUS,Z ; if it's anything else, we can't handle it bra RecvAbort ; here so return to the idle jump table bcf PORTC,RC4 ;Assert !HSHK to say we're ready to receive Receiv1 decf PORTA,W ;If we're still in state 3, keep checking xorlw B'00000110' ; " btfsc STATUS,Z ; " bra Receiv1 ; " xorlw B'00000100' ;If we're in state 1, get ready to receive; if btfss STATUS,Z ; we're in any other state, we can't handle it bra RecvAbort ; here so return to the idle jump table movlb 7 ;Clear any IOC flags that have been set up to clrf IOCAF ; now ;fall through Receiver movlp high Receiver ;Point PCLATH to this page so gotos work movlb 0 ;Point BSR to 0 so we can access PORTC bsf INTCON,GIE ;Enable interrupts so we have a way to exit RcSt0 btfss PORTC,RC5 ;Signal starts at zero, wait until transition bra $-1 ; to one, this is MSB (always 1) of first byte movlw B'10000000' ;003 cycles, 0.18 bit times movwf INDF0 ;004 cycles, 0.24 bit times btfss PORTA,RA1 ;005 cycles, 0.31 bit times bcf INDF0,7 ;006 cycles, 0.37 bit times DNOP ;007-008 cycles, 0.43-0.49 bit times btfss PORTC,RC5 ;009 cycles, 0.55 bit times goto RcTo0_6 ;010 cycles, 0.61 bit times btfss PORTC,RC5 ;011 cycles, 0.67 bit times goto RcTo0_6 ;012 cycles, 0.73 bit times btfss PORTC,RC5 ;013 cycles, 0.80 bit times goto RcTo0_6 ;014 cycles, 0.86 bit times btfss PORTC,RC5 ;015 cycles, 0.92 bit times goto RcTo0_6 ;016 cycles, 0.98 bit times btfss PORTC,RC5 ;017 cycles, 1.04 bit times goto RcTo0_6 ;018 cycles, 1.10 bit times btfss PORTC,RC5 ;019 cycles, 1.16 bit times goto RcTo0_6 ;020 cycles, 1.22 bit times btfss PORTC,RC5 ;021 cycles, 1.29 bit times goto RcTo0_6 ;022 cycles, 1.35 bit times btfss PORTC,RC5 ;023 cycles, 1.41 bit times goto RcTo0_6 ;024 cycles, 1.47 bit times btfss PORTC,RC5 ;025 cycles, 1.53 bit times goto RcTo0_5 ;026 cycles, 1.59 bit times btfss PORTC,RC5 ;027 cycles, 1.65 bit times goto RcTo0_5 ;028 cycles, 1.71 bit times btfss PORTC,RC5 ;029 cycles, 1.77 bit times goto RcTo0_5 ;030 cycles, 1.84 bit times btfss PORTC,RC5 ;031 cycles, 1.90 bit times goto RcTo0_5 ;032 cycles, 1.96 bit times btfss PORTC,RC5 ;033 cycles, 2.02 bit times goto RcTo0_5 ;034 cycles, 2.08 bit times btfss PORTC,RC5 ;035 cycles, 2.14 bit times goto RcTo0_5 ;036 cycles, 2.20 bit times btfss PORTC,RC5 ;037 cycles, 2.26 bit times goto RcTo0_5 ;038 cycles, 2.33 bit times btfss PORTC,RC5 ;039 cycles, 2.39 bit times goto RcTo0_5 ;040 cycles, 2.45 bit times btfss PORTC,RC5 ;041 cycles, 2.51 bit times goto RcTo0_4 ;042 cycles, 2.57 bit times btfss PORTC,RC5 ;043 cycles, 2.63 bit times goto RcTo0_4 ;044 cycles, 2.69 bit times btfss PORTC,RC5 ;045 cycles, 2.75 bit times goto RcTo0_4 ;046 cycles, 2.82 bit times btfss PORTC,RC5 ;047 cycles, 2.88 bit times goto RcTo0_4 ;048 cycles, 2.94 bit times btfss PORTC,RC5 ;049 cycles, 3.00 bit times goto RcTo0_4 ;050 cycles, 3.06 bit times btfss PORTC,RC5 ;051 cycles, 3.12 bit times goto RcTo0_4 ;052 cycles, 3.18 bit times btfss PORTC,RC5 ;053 cycles, 3.24 bit times goto RcTo0_4 ;054 cycles, 3.30 bit times btfss PORTC,RC5 ;055 cycles, 3.37 bit times goto RcTo0_4 ;056 cycles, 3.43 bit times btfss PORTC,RC5 ;057 cycles, 3.49 bit times goto RcTo0_4 ;058 cycles, 3.55 bit times btfss PORTC,RC5 ;059 cycles, 3.61 bit times goto RcTo0_3 ;060 cycles, 3.67 bit times btfss PORTC,RC5 ;061 cycles, 3.73 bit times goto RcTo0_3 ;062 cycles, 3.79 bit times btfss PORTC,RC5 ;063 cycles, 3.86 bit times goto RcTo0_3 ;064 cycles, 3.92 bit times btfss PORTC,RC5 ;065 cycles, 3.98 bit times goto RcTo0_3 ;066 cycles, 4.04 bit times btfss PORTC,RC5 ;067 cycles, 4.10 bit times goto RcTo0_3 ;068 cycles, 4.16 bit times btfss PORTC,RC5 ;069 cycles, 4.22 bit times goto RcTo0_3 ;070 cycles, 4.28 bit times btfss PORTC,RC5 ;071 cycles, 4.35 bit times goto RcTo0_3 ;072 cycles, 4.41 bit times btfss PORTC,RC5 ;073 cycles, 4.47 bit times goto RcTo0_3 ;074 cycles, 4.53 bit times btfss PORTC,RC5 ;075 cycles, 4.59 bit times goto RcTo0_2 ;076 cycles, 4.65 bit times btfss PORTC,RC5 ;077 cycles, 4.71 bit times goto RcTo0_2 ;078 cycles, 4.77 bit times btfss PORTC,RC5 ;079 cycles, 4.83 bit times goto RcTo0_2 ;080 cycles, 4.90 bit times btfss PORTC,RC5 ;081 cycles, 4.96 bit times goto RcTo0_2 ;082 cycles, 5.02 bit times btfss PORTC,RC5 ;083 cycles, 5.08 bit times goto RcTo0_2 ;084 cycles, 5.14 bit times btfss PORTC,RC5 ;085 cycles, 5.20 bit times goto RcTo0_2 ;086 cycles, 5.26 bit times btfss PORTC,RC5 ;087 cycles, 5.32 bit times goto RcTo0_2 ;088 cycles, 5.39 bit times btfss PORTC,RC5 ;089 cycles, 5.45 bit times goto RcTo0_2 ;090 cycles, 5.51 bit times btfss PORTC,RC5 ;091 cycles, 5.57 bit times goto RcTo0_1 ;092 cycles, 5.63 bit times btfss PORTC,RC5 ;093 cycles, 5.69 bit times goto RcTo0_1 ;094 cycles, 5.75 bit times btfss PORTC,RC5 ;095 cycles, 5.81 bit times goto RcTo0_1 ;096 cycles, 5.88 bit times btfss PORTC,RC5 ;097 cycles, 5.94 bit times goto RcTo0_1 ;098 cycles, 6.00 bit times btfss PORTC,RC5 ;099 cycles, 6.06 bit times goto RcTo0_1 ;100 cycles, 6.12 bit times btfss PORTC,RC5 ;101 cycles, 6.18 bit times goto RcTo0_1 ;102 cycles, 6.24 bit times btfss PORTC,RC5 ;103 cycles, 6.30 bit times goto RcTo0_1 ;104 cycles, 6.36 bit times btfss PORTC,RC5 ;105 cycles, 6.43 bit times goto RcTo0_1 ;106 cycles, 6.49 bit times btfss PORTC,RC5 ;107 cycles, 6.55 bit times goto RcTo0_0 ;108 cycles, 6.61 bit times btfss PORTC,RC5 ;109 cycles, 6.67 bit times goto RcTo0_0 ;110 cycles, 6.73 bit times btfss PORTC,RC5 ;111 cycles, 6.79 bit times goto RcTo0_0 ;112 cycles, 6.85 bit times btfss PORTC,RC5 ;113 cycles, 6.92 bit times goto RcTo0_0 ;114 cycles, 6.98 bit times btfss PORTC,RC5 ;115 cycles, 7.04 bit times goto RcTo0_0 ;116 cycles, 7.10 bit times btfss PORTC,RC5 ;117 cycles, 7.16 bit times goto RcTo0_0 ;118 cycles, 7.22 bit times btfss PORTC,RC5 ;119 cycles, 7.28 bit times goto RcTo0_0 ;120 cycles, 7.34 bit times btfss PORTC,RC5 ;121 cycles, 7.40 bit times goto RcTo0_0 ;122 cycles, 7.47 bit times btfss PORTA,RA1 ;123 cycles, 7.53 bit times bcf INDF0,7 ;124 cycles, 7.59 bit times addfsr FSR0,1 ;125 cycles, 7.65 bit times goto RcSt1 ;126 cycles, 7.71 bit times RcTo1_6 movlw B'01000000' ;003 cycles, 0.18 bit times iorwf INDF0,F ;004 cycles, 0.24 bit times btfss PORTA,RA1 ;005 cycles, 0.31 bit times bcf INDF0,7 ;006 cycles, 0.37 bit times DNOP ;007-008 cycles, 0.43-0.49 bit times btfss PORTC,RC5 ;009 cycles, 0.55 bit times goto RcTo0_5 ;010 cycles, 0.61 bit times btfss PORTC,RC5 ;011 cycles, 0.67 bit times goto RcTo0_5 ;012 cycles, 0.73 bit times btfss PORTC,RC5 ;013 cycles, 0.80 bit times goto RcTo0_5 ;014 cycles, 0.86 bit times btfss PORTC,RC5 ;015 cycles, 0.92 bit times goto RcTo0_5 ;016 cycles, 0.98 bit times btfss PORTC,RC5 ;017 cycles, 1.04 bit times goto RcTo0_5 ;018 cycles, 1.10 bit times btfss PORTC,RC5 ;019 cycles, 1.16 bit times goto RcTo0_5 ;020 cycles, 1.22 bit times btfss PORTC,RC5 ;021 cycles, 1.29 bit times goto RcTo0_5 ;022 cycles, 1.35 bit times btfss PORTC,RC5 ;023 cycles, 1.41 bit times goto RcTo0_5 ;024 cycles, 1.47 bit times btfss PORTC,RC5 ;025 cycles, 1.53 bit times goto RcTo0_4 ;026 cycles, 1.59 bit times btfss PORTC,RC5 ;027 cycles, 1.65 bit times goto RcTo0_4 ;028 cycles, 1.71 bit times btfss PORTC,RC5 ;029 cycles, 1.77 bit times goto RcTo0_4 ;030 cycles, 1.84 bit times btfss PORTC,RC5 ;031 cycles, 1.90 bit times goto RcTo0_4 ;032 cycles, 1.96 bit times btfss PORTC,RC5 ;033 cycles, 2.02 bit times goto RcTo0_4 ;034 cycles, 2.08 bit times btfss PORTC,RC5 ;035 cycles, 2.14 bit times goto RcTo0_4 ;036 cycles, 2.20 bit times btfss PORTC,RC5 ;037 cycles, 2.26 bit times goto RcTo0_4 ;038 cycles, 2.33 bit times btfss PORTC,RC5 ;039 cycles, 2.39 bit times goto RcTo0_4 ;040 cycles, 2.45 bit times btfss PORTC,RC5 ;041 cycles, 2.51 bit times goto RcTo0_3 ;042 cycles, 2.57 bit times btfss PORTC,RC5 ;043 cycles, 2.63 bit times goto RcTo0_3 ;044 cycles, 2.69 bit times btfss PORTC,RC5 ;045 cycles, 2.75 bit times goto RcTo0_3 ;046 cycles, 2.82 bit times btfss PORTC,RC5 ;047 cycles, 2.88 bit times goto RcTo0_3 ;048 cycles, 2.94 bit times btfss PORTC,RC5 ;049 cycles, 3.00 bit times goto RcTo0_3 ;050 cycles, 3.06 bit times btfss PORTC,RC5 ;051 cycles, 3.12 bit times goto RcTo0_3 ;052 cycles, 3.18 bit times btfss PORTC,RC5 ;053 cycles, 3.24 bit times goto RcTo0_3 ;054 cycles, 3.30 bit times btfss PORTC,RC5 ;055 cycles, 3.37 bit times goto RcTo0_3 ;056 cycles, 3.43 bit times btfss PORTC,RC5 ;057 cycles, 3.49 bit times goto RcTo0_3 ;058 cycles, 3.55 bit times btfss PORTC,RC5 ;059 cycles, 3.61 bit times goto RcTo0_2 ;060 cycles, 3.67 bit times btfss PORTC,RC5 ;061 cycles, 3.73 bit times goto RcTo0_2 ;062 cycles, 3.79 bit times btfss PORTC,RC5 ;063 cycles, 3.86 bit times goto RcTo0_2 ;064 cycles, 3.92 bit times btfss PORTC,RC5 ;065 cycles, 3.98 bit times goto RcTo0_2 ;066 cycles, 4.04 bit times btfss PORTC,RC5 ;067 cycles, 4.10 bit times goto RcTo0_2 ;068 cycles, 4.16 bit times btfss PORTC,RC5 ;069 cycles, 4.22 bit times goto RcTo0_2 ;070 cycles, 4.28 bit times btfss PORTC,RC5 ;071 cycles, 4.35 bit times goto RcTo0_2 ;072 cycles, 4.41 bit times btfss PORTC,RC5 ;073 cycles, 4.47 bit times goto RcTo0_2 ;074 cycles, 4.53 bit times btfss PORTC,RC5 ;075 cycles, 4.59 bit times goto RcTo0_1 ;076 cycles, 4.65 bit times btfss PORTC,RC5 ;077 cycles, 4.71 bit times goto RcTo0_1 ;078 cycles, 4.77 bit times btfss PORTC,RC5 ;079 cycles, 4.83 bit times goto RcTo0_1 ;080 cycles, 4.90 bit times btfss PORTC,RC5 ;081 cycles, 4.96 bit times goto RcTo0_1 ;082 cycles, 5.02 bit times btfss PORTC,RC5 ;083 cycles, 5.08 bit times goto RcTo0_1 ;084 cycles, 5.14 bit times btfss PORTC,RC5 ;085 cycles, 5.20 bit times goto RcTo0_1 ;086 cycles, 5.26 bit times btfss PORTC,RC5 ;087 cycles, 5.32 bit times goto RcTo0_1 ;088 cycles, 5.39 bit times btfss PORTC,RC5 ;089 cycles, 5.45 bit times goto RcTo0_1 ;090 cycles, 5.51 bit times btfss PORTC,RC5 ;091 cycles, 5.57 bit times goto RcTo0_0 ;092 cycles, 5.63 bit times btfss PORTC,RC5 ;093 cycles, 5.69 bit times goto RcTo0_0 ;094 cycles, 5.75 bit times btfss PORTC,RC5 ;095 cycles, 5.81 bit times goto RcTo0_0 ;096 cycles, 5.88 bit times btfss PORTC,RC5 ;097 cycles, 5.94 bit times goto RcTo0_0 ;098 cycles, 6.00 bit times btfss PORTC,RC5 ;099 cycles, 6.06 bit times goto RcTo0_0 ;100 cycles, 6.12 bit times btfss PORTC,RC5 ;101 cycles, 6.18 bit times goto RcTo0_0 ;102 cycles, 6.24 bit times btfss PORTC,RC5 ;103 cycles, 6.30 bit times goto RcTo0_0 ;104 cycles, 6.36 bit times btfss PORTC,RC5 ;105 cycles, 6.43 bit times goto RcTo0_0 ;106 cycles, 6.49 bit times btfss PORTA,RA1 ;107 cycles, 6.55 bit times bcf INDF0,7 ;108 cycles, 6.61 bit times addfsr FSR0,1 ;109 cycles, 6.67 bit times goto RcSt1 ;110 cycles, 6.73 bit times RcTo1_5 movlw B'00100000' ;003 cycles, 0.18 bit times iorwf INDF0,F ;004 cycles, 0.24 bit times btfss PORTA,RA1 ;005 cycles, 0.31 bit times bcf INDF0,7 ;006 cycles, 0.37 bit times DNOP ;007-008 cycles, 0.43-0.49 bit times btfss PORTC,RC5 ;009 cycles, 0.55 bit times goto RcTo0_4 ;010 cycles, 0.61 bit times btfss PORTC,RC5 ;011 cycles, 0.67 bit times goto RcTo0_4 ;012 cycles, 0.73 bit times btfss PORTC,RC5 ;013 cycles, 0.80 bit times goto RcTo0_4 ;014 cycles, 0.86 bit times btfss PORTC,RC5 ;015 cycles, 0.92 bit times goto RcTo0_4 ;016 cycles, 0.98 bit times btfss PORTC,RC5 ;017 cycles, 1.04 bit times goto RcTo0_4 ;018 cycles, 1.10 bit times btfss PORTC,RC5 ;019 cycles, 1.16 bit times goto RcTo0_4 ;020 cycles, 1.22 bit times btfss PORTC,RC5 ;021 cycles, 1.29 bit times goto RcTo0_4 ;022 cycles, 1.35 bit times btfss PORTC,RC5 ;023 cycles, 1.41 bit times goto RcTo0_4 ;024 cycles, 1.47 bit times btfss PORTC,RC5 ;025 cycles, 1.53 bit times goto RcTo0_3 ;026 cycles, 1.59 bit times btfss PORTC,RC5 ;027 cycles, 1.65 bit times goto RcTo0_3 ;028 cycles, 1.71 bit times btfss PORTC,RC5 ;029 cycles, 1.77 bit times goto RcTo0_3 ;030 cycles, 1.84 bit times btfss PORTC,RC5 ;031 cycles, 1.90 bit times goto RcTo0_3 ;032 cycles, 1.96 bit times btfss PORTC,RC5 ;033 cycles, 2.02 bit times goto RcTo0_3 ;034 cycles, 2.08 bit times btfss PORTC,RC5 ;035 cycles, 2.14 bit times goto RcTo0_3 ;036 cycles, 2.20 bit times btfss PORTC,RC5 ;037 cycles, 2.26 bit times goto RcTo0_3 ;038 cycles, 2.33 bit times btfss PORTC,RC5 ;039 cycles, 2.39 bit times goto RcTo0_3 ;040 cycles, 2.45 bit times btfss PORTC,RC5 ;041 cycles, 2.51 bit times goto RcTo0_2 ;042 cycles, 2.57 bit times btfss PORTC,RC5 ;043 cycles, 2.63 bit times goto RcTo0_2 ;044 cycles, 2.69 bit times btfss PORTC,RC5 ;045 cycles, 2.75 bit times goto RcTo0_2 ;046 cycles, 2.82 bit times btfss PORTC,RC5 ;047 cycles, 2.88 bit times goto RcTo0_2 ;048 cycles, 2.94 bit times btfss PORTC,RC5 ;049 cycles, 3.00 bit times goto RcTo0_2 ;050 cycles, 3.06 bit times btfss PORTC,RC5 ;051 cycles, 3.12 bit times goto RcTo0_2 ;052 cycles, 3.18 bit times btfss PORTC,RC5 ;053 cycles, 3.24 bit times goto RcTo0_2 ;054 cycles, 3.30 bit times btfss PORTC,RC5 ;055 cycles, 3.37 bit times goto RcTo0_2 ;056 cycles, 3.43 bit times btfss PORTC,RC5 ;057 cycles, 3.49 bit times goto RcTo0_2 ;058 cycles, 3.55 bit times btfss PORTC,RC5 ;059 cycles, 3.61 bit times goto RcTo0_1 ;060 cycles, 3.67 bit times btfss PORTC,RC5 ;061 cycles, 3.73 bit times goto RcTo0_1 ;062 cycles, 3.79 bit times btfss PORTC,RC5 ;063 cycles, 3.86 bit times goto RcTo0_1 ;064 cycles, 3.92 bit times btfss PORTC,RC5 ;065 cycles, 3.98 bit times goto RcTo0_1 ;066 cycles, 4.04 bit times btfss PORTC,RC5 ;067 cycles, 4.10 bit times goto RcTo0_1 ;068 cycles, 4.16 bit times btfss PORTC,RC5 ;069 cycles, 4.22 bit times goto RcTo0_1 ;070 cycles, 4.28 bit times btfss PORTC,RC5 ;071 cycles, 4.35 bit times goto RcTo0_1 ;072 cycles, 4.41 bit times btfss PORTC,RC5 ;073 cycles, 4.47 bit times goto RcTo0_1 ;074 cycles, 4.53 bit times btfss PORTC,RC5 ;075 cycles, 4.59 bit times goto RcTo0_0 ;076 cycles, 4.65 bit times btfss PORTC,RC5 ;077 cycles, 4.71 bit times goto RcTo0_0 ;078 cycles, 4.77 bit times btfss PORTC,RC5 ;079 cycles, 4.83 bit times goto RcTo0_0 ;080 cycles, 4.90 bit times btfss PORTC,RC5 ;081 cycles, 4.96 bit times goto RcTo0_0 ;082 cycles, 5.02 bit times btfss PORTC,RC5 ;083 cycles, 5.08 bit times goto RcTo0_0 ;084 cycles, 5.14 bit times btfss PORTC,RC5 ;085 cycles, 5.20 bit times goto RcTo0_0 ;086 cycles, 5.26 bit times btfss PORTC,RC5 ;087 cycles, 5.32 bit times goto RcTo0_0 ;088 cycles, 5.39 bit times btfss PORTC,RC5 ;089 cycles, 5.45 bit times goto RcTo0_0 ;090 cycles, 5.51 bit times btfss PORTA,RA1 ;091 cycles, 5.57 bit times bcf INDF0,7 ;092 cycles, 5.63 bit times addfsr FSR0,1 ;093 cycles, 5.69 bit times goto RcSt1 ;094 cycles, 5.75 bit times RcTo1_4 movlw B'00010000' ;003 cycles, 0.18 bit times iorwf INDF0,F ;004 cycles, 0.24 bit times btfss PORTA,RA1 ;005 cycles, 0.31 bit times bcf INDF0,7 ;006 cycles, 0.37 bit times DNOP ;007-008 cycles, 0.43-0.49 bit times btfss PORTC,RC5 ;009 cycles, 0.55 bit times goto RcTo0_3 ;010 cycles, 0.61 bit times btfss PORTC,RC5 ;011 cycles, 0.67 bit times goto RcTo0_3 ;012 cycles, 0.73 bit times btfss PORTC,RC5 ;013 cycles, 0.80 bit times goto RcTo0_3 ;014 cycles, 0.86 bit times btfss PORTC,RC5 ;015 cycles, 0.92 bit times goto RcTo0_3 ;016 cycles, 0.98 bit times btfss PORTC,RC5 ;017 cycles, 1.04 bit times goto RcTo0_3 ;018 cycles, 1.10 bit times btfss PORTC,RC5 ;019 cycles, 1.16 bit times goto RcTo0_3 ;020 cycles, 1.22 bit times btfss PORTC,RC5 ;021 cycles, 1.29 bit times goto RcTo0_3 ;022 cycles, 1.35 bit times btfss PORTC,RC5 ;023 cycles, 1.41 bit times goto RcTo0_3 ;024 cycles, 1.47 bit times btfss PORTC,RC5 ;025 cycles, 1.53 bit times goto RcTo0_2 ;026 cycles, 1.59 bit times btfss PORTC,RC5 ;027 cycles, 1.65 bit times goto RcTo0_2 ;028 cycles, 1.71 bit times btfss PORTC,RC5 ;029 cycles, 1.77 bit times goto RcTo0_2 ;030 cycles, 1.84 bit times btfss PORTC,RC5 ;031 cycles, 1.90 bit times goto RcTo0_2 ;032 cycles, 1.96 bit times btfss PORTC,RC5 ;033 cycles, 2.02 bit times goto RcTo0_2 ;034 cycles, 2.08 bit times btfss PORTC,RC5 ;035 cycles, 2.14 bit times goto RcTo0_2 ;036 cycles, 2.20 bit times btfss PORTC,RC5 ;037 cycles, 2.26 bit times goto RcTo0_2 ;038 cycles, 2.33 bit times btfss PORTC,RC5 ;039 cycles, 2.39 bit times goto RcTo0_2 ;040 cycles, 2.45 bit times btfss PORTC,RC5 ;041 cycles, 2.51 bit times goto RcTo0_1 ;042 cycles, 2.57 bit times btfss PORTC,RC5 ;043 cycles, 2.63 bit times goto RcTo0_1 ;044 cycles, 2.69 bit times btfss PORTC,RC5 ;045 cycles, 2.75 bit times goto RcTo0_1 ;046 cycles, 2.82 bit times btfss PORTC,RC5 ;047 cycles, 2.88 bit times goto RcTo0_1 ;048 cycles, 2.94 bit times btfss PORTC,RC5 ;049 cycles, 3.00 bit times goto RcTo0_1 ;050 cycles, 3.06 bit times btfss PORTC,RC5 ;051 cycles, 3.12 bit times goto RcTo0_1 ;052 cycles, 3.18 bit times btfss PORTC,RC5 ;053 cycles, 3.24 bit times goto RcTo0_1 ;054 cycles, 3.30 bit times btfss PORTC,RC5 ;055 cycles, 3.37 bit times goto RcTo0_1 ;056 cycles, 3.43 bit times btfss PORTC,RC5 ;057 cycles, 3.49 bit times goto RcTo0_1 ;058 cycles, 3.55 bit times btfss PORTC,RC5 ;059 cycles, 3.61 bit times goto RcTo0_0 ;060 cycles, 3.67 bit times btfss PORTC,RC5 ;061 cycles, 3.73 bit times goto RcTo0_0 ;062 cycles, 3.79 bit times btfss PORTC,RC5 ;063 cycles, 3.86 bit times goto RcTo0_0 ;064 cycles, 3.92 bit times btfss PORTC,RC5 ;065 cycles, 3.98 bit times goto RcTo0_0 ;066 cycles, 4.04 bit times btfss PORTC,RC5 ;067 cycles, 4.10 bit times goto RcTo0_0 ;068 cycles, 4.16 bit times btfss PORTC,RC5 ;069 cycles, 4.22 bit times goto RcTo0_0 ;070 cycles, 4.28 bit times btfss PORTC,RC5 ;071 cycles, 4.35 bit times goto RcTo0_0 ;072 cycles, 4.41 bit times btfss PORTC,RC5 ;073 cycles, 4.47 bit times goto RcTo0_0 ;074 cycles, 4.53 bit times btfss PORTA,RA1 ;075 cycles, 4.59 bit times bcf INDF0,7 ;076 cycles, 4.65 bit times addfsr FSR0,1 ;077 cycles, 4.71 bit times goto RcSt1 ;078 cycles, 4.77 bit times RcTo1_3 movlw B'00001000' ;003 cycles, 0.18 bit times iorwf INDF0,F ;004 cycles, 0.24 bit times btfss PORTA,RA1 ;005 cycles, 0.31 bit times bcf INDF0,7 ;006 cycles, 0.37 bit times DNOP ;007-008 cycles, 0.43-0.49 bit times btfss PORTC,RC5 ;009 cycles, 0.55 bit times goto RcTo0_2 ;010 cycles, 0.61 bit times btfss PORTC,RC5 ;011 cycles, 0.67 bit times goto RcTo0_2 ;012 cycles, 0.73 bit times btfss PORTC,RC5 ;013 cycles, 0.80 bit times goto RcTo0_2 ;014 cycles, 0.86 bit times btfss PORTC,RC5 ;015 cycles, 0.92 bit times goto RcTo0_2 ;016 cycles, 0.98 bit times btfss PORTC,RC5 ;017 cycles, 1.04 bit times goto RcTo0_2 ;018 cycles, 1.10 bit times btfss PORTC,RC5 ;019 cycles, 1.16 bit times goto RcTo0_2 ;020 cycles, 1.22 bit times btfss PORTC,RC5 ;021 cycles, 1.29 bit times goto RcTo0_2 ;022 cycles, 1.35 bit times btfss PORTC,RC5 ;023 cycles, 1.41 bit times goto RcTo0_2 ;024 cycles, 1.47 bit times btfss PORTC,RC5 ;025 cycles, 1.53 bit times goto RcTo0_1 ;026 cycles, 1.59 bit times btfss PORTC,RC5 ;027 cycles, 1.65 bit times goto RcTo0_1 ;028 cycles, 1.71 bit times btfss PORTC,RC5 ;029 cycles, 1.77 bit times goto RcTo0_1 ;030 cycles, 1.84 bit times btfss PORTC,RC5 ;031 cycles, 1.90 bit times goto RcTo0_1 ;032 cycles, 1.96 bit times btfss PORTC,RC5 ;033 cycles, 2.02 bit times goto RcTo0_1 ;034 cycles, 2.08 bit times btfss PORTC,RC5 ;035 cycles, 2.14 bit times goto RcTo0_1 ;036 cycles, 2.20 bit times btfss PORTC,RC5 ;037 cycles, 2.26 bit times goto RcTo0_1 ;038 cycles, 2.33 bit times btfss PORTC,RC5 ;039 cycles, 2.39 bit times goto RcTo0_1 ;040 cycles, 2.45 bit times btfss PORTC,RC5 ;041 cycles, 2.51 bit times goto RcTo0_0 ;042 cycles, 2.57 bit times btfss PORTC,RC5 ;043 cycles, 2.63 bit times goto RcTo0_0 ;044 cycles, 2.69 bit times btfss PORTC,RC5 ;045 cycles, 2.75 bit times goto RcTo0_0 ;046 cycles, 2.82 bit times btfss PORTC,RC5 ;047 cycles, 2.88 bit times goto RcTo0_0 ;048 cycles, 2.94 bit times btfss PORTC,RC5 ;049 cycles, 3.00 bit times goto RcTo0_0 ;050 cycles, 3.06 bit times btfss PORTC,RC5 ;051 cycles, 3.12 bit times goto RcTo0_0 ;052 cycles, 3.18 bit times btfss PORTC,RC5 ;053 cycles, 3.24 bit times goto RcTo0_0 ;054 cycles, 3.30 bit times btfss PORTC,RC5 ;055 cycles, 3.37 bit times goto RcTo0_0 ;056 cycles, 3.43 bit times btfss PORTC,RC5 ;057 cycles, 3.49 bit times goto RcTo0_0 ;058 cycles, 3.55 bit times btfss PORTA,RA1 ;059 cycles, 3.61 bit times bcf INDF0,7 ;060 cycles, 3.67 bit times addfsr FSR0,1 ;061 cycles, 3.73 bit times goto RcSt1 ;062 cycles, 3.79 bit times RcTo1_2 movlw B'00000100' ;003 cycles, 0.18 bit times iorwf INDF0,F ;004 cycles, 0.24 bit times btfss PORTA,RA1 ;005 cycles, 0.31 bit times bcf INDF0,7 ;006 cycles, 0.37 bit times DNOP ;007-008 cycles, 0.43-0.49 bit times btfss PORTC,RC5 ;009 cycles, 0.55 bit times goto RcTo0_1 ;010 cycles, 0.61 bit times btfss PORTC,RC5 ;011 cycles, 0.67 bit times goto RcTo0_1 ;012 cycles, 0.73 bit times btfss PORTC,RC5 ;013 cycles, 0.80 bit times goto RcTo0_1 ;014 cycles, 0.86 bit times btfss PORTC,RC5 ;015 cycles, 0.92 bit times goto RcTo0_1 ;016 cycles, 0.98 bit times btfss PORTC,RC5 ;017 cycles, 1.04 bit times goto RcTo0_1 ;018 cycles, 1.10 bit times btfss PORTC,RC5 ;019 cycles, 1.16 bit times goto RcTo0_1 ;020 cycles, 1.22 bit times btfss PORTC,RC5 ;021 cycles, 1.29 bit times goto RcTo0_1 ;022 cycles, 1.35 bit times btfss PORTC,RC5 ;023 cycles, 1.41 bit times goto RcTo0_1 ;024 cycles, 1.47 bit times btfss PORTC,RC5 ;025 cycles, 1.53 bit times goto RcTo0_0 ;026 cycles, 1.59 bit times btfss PORTC,RC5 ;027 cycles, 1.65 bit times goto RcTo0_0 ;028 cycles, 1.71 bit times btfss PORTC,RC5 ;029 cycles, 1.77 bit times goto RcTo0_0 ;030 cycles, 1.84 bit times btfss PORTC,RC5 ;031 cycles, 1.90 bit times goto RcTo0_0 ;032 cycles, 1.96 bit times btfss PORTC,RC5 ;033 cycles, 2.02 bit times goto RcTo0_0 ;034 cycles, 2.08 bit times btfss PORTC,RC5 ;035 cycles, 2.14 bit times goto RcTo0_0 ;036 cycles, 2.20 bit times btfss PORTC,RC5 ;037 cycles, 2.26 bit times goto RcTo0_0 ;038 cycles, 2.33 bit times btfss PORTC,RC5 ;039 cycles, 2.39 bit times goto RcTo0_0 ;040 cycles, 2.45 bit times btfss PORTA,RA1 ;041 cycles, 2.51 bit times bcf INDF0,7 ;042 cycles, 2.57 bit times addfsr FSR0,1 ;043 cycles, 2.63 bit times goto RcSt1 ;044 cycles, 2.69 bit times RcTo1_1 movlw B'00000010' ;003 cycles, 0.18 bit times iorwf INDF0,F ;004 cycles, 0.24 bit times btfss PORTA,RA1 ;005 cycles, 0.31 bit times bcf INDF0,7 ;006 cycles, 0.37 bit times DNOP ;007-008 cycles, 0.43-0.49 bit times btfss PORTC,RC5 ;009 cycles, 0.55 bit times goto RcTo0_0 ;010 cycles, 0.61 bit times btfss PORTC,RC5 ;011 cycles, 0.67 bit times goto RcTo0_0 ;012 cycles, 0.73 bit times btfss PORTC,RC5 ;013 cycles, 0.80 bit times goto RcTo0_0 ;014 cycles, 0.86 bit times btfss PORTC,RC5 ;015 cycles, 0.92 bit times goto RcTo0_0 ;016 cycles, 0.98 bit times btfss PORTC,RC5 ;017 cycles, 1.04 bit times goto RcTo0_0 ;018 cycles, 1.10 bit times btfss PORTC,RC5 ;019 cycles, 1.16 bit times goto RcTo0_0 ;020 cycles, 1.22 bit times btfss PORTC,RC5 ;021 cycles, 1.29 bit times goto RcTo0_0 ;022 cycles, 1.35 bit times btfss PORTC,RC5 ;023 cycles, 1.41 bit times goto RcTo0_0 ;024 cycles, 1.47 bit times btfss PORTA,RA1 ;025 cycles, 1.53 bit times bcf INDF0,7 ;026 cycles, 1.59 bit times addfsr FSR0,1 ;027 cycles, 1.65 bit times goto RcSt1 ;028 cycles, 1.71 bit times RcTo1_0 movlw B'00000001' ;003 cycles, 0.18 bit times iorwf INDF0,F ;004 cycles, 0.24 bit times btfss PORTA,RA1 ;005 cycles, 0.31 bit times bcf INDF0,7 ;006 cycles, 0.37 bit times addfsr FSR0,1 ;007 cycles, 0.43 bit times ;fall through RcSt1 btfsc PORTC,RC5 ;Signal starts at one, wait until transition bra $-1 ; to zero, this is MSB (always 1) of first byte movlw B'10000000' ;003 cycles, 0.18 bit times movwf INDF0 ;004 cycles, 0.24 bit times btfss PORTA,RA1 ;005 cycles, 0.31 bit times bcf INDF0,7 ;006 cycles, 0.37 bit times DNOP ;007-008 cycles, 0.43-0.49 bit times btfsc PORTC,RC5 ;009 cycles, 0.55 bit times goto RcTo1_6 ;010 cycles, 0.61 bit times btfsc PORTC,RC5 ;011 cycles, 0.67 bit times goto RcTo1_6 ;012 cycles, 0.73 bit times btfsc PORTC,RC5 ;013 cycles, 0.80 bit times goto RcTo1_6 ;014 cycles, 0.86 bit times btfsc PORTC,RC5 ;015 cycles, 0.92 bit times goto RcTo1_6 ;016 cycles, 0.98 bit times btfsc PORTC,RC5 ;017 cycles, 1.04 bit times goto RcTo1_6 ;018 cycles, 1.10 bit times btfsc PORTC,RC5 ;019 cycles, 1.16 bit times goto RcTo1_6 ;020 cycles, 1.22 bit times btfsc PORTC,RC5 ;021 cycles, 1.29 bit times goto RcTo1_6 ;022 cycles, 1.35 bit times btfsc PORTC,RC5 ;023 cycles, 1.41 bit times goto RcTo1_6 ;024 cycles, 1.47 bit times btfsc PORTC,RC5 ;025 cycles, 1.53 bit times goto RcTo1_5 ;026 cycles, 1.59 bit times btfsc PORTC,RC5 ;027 cycles, 1.65 bit times goto RcTo1_5 ;028 cycles, 1.71 bit times btfsc PORTC,RC5 ;029 cycles, 1.77 bit times goto RcTo1_5 ;030 cycles, 1.84 bit times btfsc PORTC,RC5 ;031 cycles, 1.90 bit times goto RcTo1_5 ;032 cycles, 1.96 bit times btfsc PORTC,RC5 ;033 cycles, 2.02 bit times goto RcTo1_5 ;034 cycles, 2.08 bit times btfsc PORTC,RC5 ;035 cycles, 2.14 bit times goto RcTo1_5 ;036 cycles, 2.20 bit times btfsc PORTC,RC5 ;037 cycles, 2.26 bit times goto RcTo1_5 ;038 cycles, 2.33 bit times btfsc PORTC,RC5 ;039 cycles, 2.39 bit times goto RcTo1_5 ;040 cycles, 2.45 bit times btfsc PORTC,RC5 ;041 cycles, 2.51 bit times goto RcTo1_4 ;042 cycles, 2.57 bit times btfsc PORTC,RC5 ;043 cycles, 2.63 bit times goto RcTo1_4 ;044 cycles, 2.69 bit times btfsc PORTC,RC5 ;045 cycles, 2.75 bit times goto RcTo1_4 ;046 cycles, 2.82 bit times btfsc PORTC,RC5 ;047 cycles, 2.88 bit times goto RcTo1_4 ;048 cycles, 2.94 bit times btfsc PORTC,RC5 ;049 cycles, 3.00 bit times goto RcTo1_4 ;050 cycles, 3.06 bit times btfsc PORTC,RC5 ;051 cycles, 3.12 bit times goto RcTo1_4 ;052 cycles, 3.18 bit times btfsc PORTC,RC5 ;053 cycles, 3.24 bit times goto RcTo1_4 ;054 cycles, 3.30 bit times btfsc PORTC,RC5 ;055 cycles, 3.37 bit times goto RcTo1_4 ;056 cycles, 3.43 bit times btfsc PORTC,RC5 ;057 cycles, 3.49 bit times goto RcTo1_4 ;058 cycles, 3.55 bit times btfsc PORTC,RC5 ;059 cycles, 3.61 bit times goto RcTo1_3 ;060 cycles, 3.67 bit times btfsc PORTC,RC5 ;061 cycles, 3.73 bit times goto RcTo1_3 ;062 cycles, 3.79 bit times btfsc PORTC,RC5 ;063 cycles, 3.86 bit times goto RcTo1_3 ;064 cycles, 3.92 bit times btfsc PORTC,RC5 ;065 cycles, 3.98 bit times goto RcTo1_3 ;066 cycles, 4.04 bit times btfsc PORTC,RC5 ;067 cycles, 4.10 bit times goto RcTo1_3 ;068 cycles, 4.16 bit times btfsc PORTC,RC5 ;069 cycles, 4.22 bit times goto RcTo1_3 ;070 cycles, 4.28 bit times btfsc PORTC,RC5 ;071 cycles, 4.35 bit times goto RcTo1_3 ;072 cycles, 4.41 bit times btfsc PORTC,RC5 ;073 cycles, 4.47 bit times goto RcTo1_3 ;074 cycles, 4.53 bit times btfsc PORTC,RC5 ;075 cycles, 4.59 bit times goto RcTo1_2 ;076 cycles, 4.65 bit times btfsc PORTC,RC5 ;077 cycles, 4.71 bit times goto RcTo1_2 ;078 cycles, 4.77 bit times btfsc PORTC,RC5 ;079 cycles, 4.83 bit times goto RcTo1_2 ;080 cycles, 4.90 bit times btfsc PORTC,RC5 ;081 cycles, 4.96 bit times goto RcTo1_2 ;082 cycles, 5.02 bit times btfsc PORTC,RC5 ;083 cycles, 5.08 bit times goto RcTo1_2 ;084 cycles, 5.14 bit times btfsc PORTC,RC5 ;085 cycles, 5.20 bit times goto RcTo1_2 ;086 cycles, 5.26 bit times btfsc PORTC,RC5 ;087 cycles, 5.32 bit times goto RcTo1_2 ;088 cycles, 5.39 bit times btfsc PORTC,RC5 ;089 cycles, 5.45 bit times goto RcTo1_2 ;090 cycles, 5.51 bit times btfsc PORTC,RC5 ;091 cycles, 5.57 bit times goto RcTo1_1 ;092 cycles, 5.63 bit times btfsc PORTC,RC5 ;093 cycles, 5.69 bit times goto RcTo1_1 ;094 cycles, 5.75 bit times btfsc PORTC,RC5 ;095 cycles, 5.81 bit times goto RcTo1_1 ;096 cycles, 5.88 bit times btfsc PORTC,RC5 ;097 cycles, 5.94 bit times goto RcTo1_1 ;098 cycles, 6.00 bit times btfsc PORTC,RC5 ;099 cycles, 6.06 bit times goto RcTo1_1 ;100 cycles, 6.12 bit times btfsc PORTC,RC5 ;101 cycles, 6.18 bit times goto RcTo1_1 ;102 cycles, 6.24 bit times btfsc PORTC,RC5 ;103 cycles, 6.30 bit times goto RcTo1_1 ;104 cycles, 6.36 bit times btfsc PORTC,RC5 ;105 cycles, 6.43 bit times goto RcTo1_1 ;106 cycles, 6.49 bit times btfsc PORTC,RC5 ;107 cycles, 6.55 bit times goto RcTo1_0 ;108 cycles, 6.61 bit times btfsc PORTC,RC5 ;109 cycles, 6.67 bit times goto RcTo1_0 ;110 cycles, 6.73 bit times btfsc PORTC,RC5 ;111 cycles, 6.79 bit times goto RcTo1_0 ;112 cycles, 6.85 bit times btfsc PORTC,RC5 ;113 cycles, 6.92 bit times goto RcTo1_0 ;114 cycles, 6.98 bit times btfsc PORTC,RC5 ;115 cycles, 7.04 bit times goto RcTo1_0 ;116 cycles, 7.10 bit times btfsc PORTC,RC5 ;117 cycles, 7.16 bit times goto RcTo1_0 ;118 cycles, 7.22 bit times btfsc PORTC,RC5 ;119 cycles, 7.28 bit times goto RcTo1_0 ;120 cycles, 7.34 bit times btfsc PORTC,RC5 ;121 cycles, 7.40 bit times goto RcTo1_0 ;122 cycles, 7.47 bit times btfss PORTA,RA1 ;123 cycles, 7.53 bit times bcf INDF0,7 ;124 cycles, 7.59 bit times addfsr FSR0,1 ;125 cycles, 7.65 bit times goto RcSt0 ;126 cycles, 7.71 bit times RcTo0_6 movlw B'01000000' ;003 cycles, 0.18 bit times iorwf INDF0,F ;004 cycles, 0.24 bit times btfss PORTA,RA1 ;005 cycles, 0.31 bit times bcf INDF0,7 ;006 cycles, 0.37 bit times DNOP ;007-008 cycles, 0.43-0.49 bit times btfsc PORTC,RC5 ;009 cycles, 0.55 bit times goto RcTo1_5 ;010 cycles, 0.61 bit times btfsc PORTC,RC5 ;011 cycles, 0.67 bit times goto RcTo1_5 ;012 cycles, 0.73 bit times btfsc PORTC,RC5 ;013 cycles, 0.80 bit times goto RcTo1_5 ;014 cycles, 0.86 bit times btfsc PORTC,RC5 ;015 cycles, 0.92 bit times goto RcTo1_5 ;016 cycles, 0.98 bit times btfsc PORTC,RC5 ;017 cycles, 1.04 bit times goto RcTo1_5 ;018 cycles, 1.10 bit times btfsc PORTC,RC5 ;019 cycles, 1.16 bit times goto RcTo1_5 ;020 cycles, 1.22 bit times btfsc PORTC,RC5 ;021 cycles, 1.29 bit times goto RcTo1_5 ;022 cycles, 1.35 bit times btfsc PORTC,RC5 ;023 cycles, 1.41 bit times goto RcTo1_5 ;024 cycles, 1.47 bit times btfsc PORTC,RC5 ;025 cycles, 1.53 bit times goto RcTo1_4 ;026 cycles, 1.59 bit times btfsc PORTC,RC5 ;027 cycles, 1.65 bit times goto RcTo1_4 ;028 cycles, 1.71 bit times btfsc PORTC,RC5 ;029 cycles, 1.77 bit times goto RcTo1_4 ;030 cycles, 1.84 bit times btfsc PORTC,RC5 ;031 cycles, 1.90 bit times goto RcTo1_4 ;032 cycles, 1.96 bit times btfsc PORTC,RC5 ;033 cycles, 2.02 bit times goto RcTo1_4 ;034 cycles, 2.08 bit times btfsc PORTC,RC5 ;035 cycles, 2.14 bit times goto RcTo1_4 ;036 cycles, 2.20 bit times btfsc PORTC,RC5 ;037 cycles, 2.26 bit times goto RcTo1_4 ;038 cycles, 2.33 bit times btfsc PORTC,RC5 ;039 cycles, 2.39 bit times goto RcTo1_4 ;040 cycles, 2.45 bit times btfsc PORTC,RC5 ;041 cycles, 2.51 bit times goto RcTo1_3 ;042 cycles, 2.57 bit times btfsc PORTC,RC5 ;043 cycles, 2.63 bit times goto RcTo1_3 ;044 cycles, 2.69 bit times btfsc PORTC,RC5 ;045 cycles, 2.75 bit times goto RcTo1_3 ;046 cycles, 2.82 bit times btfsc PORTC,RC5 ;047 cycles, 2.88 bit times goto RcTo1_3 ;048 cycles, 2.94 bit times btfsc PORTC,RC5 ;049 cycles, 3.00 bit times goto RcTo1_3 ;050 cycles, 3.06 bit times btfsc PORTC,RC5 ;051 cycles, 3.12 bit times goto RcTo1_3 ;052 cycles, 3.18 bit times btfsc PORTC,RC5 ;053 cycles, 3.24 bit times goto RcTo1_3 ;054 cycles, 3.30 bit times btfsc PORTC,RC5 ;055 cycles, 3.37 bit times goto RcTo1_3 ;056 cycles, 3.43 bit times btfsc PORTC,RC5 ;057 cycles, 3.49 bit times goto RcTo1_3 ;058 cycles, 3.55 bit times btfsc PORTC,RC5 ;059 cycles, 3.61 bit times goto RcTo1_2 ;060 cycles, 3.67 bit times btfsc PORTC,RC5 ;061 cycles, 3.73 bit times goto RcTo1_2 ;062 cycles, 3.79 bit times btfsc PORTC,RC5 ;063 cycles, 3.86 bit times goto RcTo1_2 ;064 cycles, 3.92 bit times btfsc PORTC,RC5 ;065 cycles, 3.98 bit times goto RcTo1_2 ;066 cycles, 4.04 bit times btfsc PORTC,RC5 ;067 cycles, 4.10 bit times goto RcTo1_2 ;068 cycles, 4.16 bit times btfsc PORTC,RC5 ;069 cycles, 4.22 bit times goto RcTo1_2 ;070 cycles, 4.28 bit times btfsc PORTC,RC5 ;071 cycles, 4.35 bit times goto RcTo1_2 ;072 cycles, 4.41 bit times btfsc PORTC,RC5 ;073 cycles, 4.47 bit times goto RcTo1_2 ;074 cycles, 4.53 bit times btfsc PORTC,RC5 ;075 cycles, 4.59 bit times goto RcTo1_1 ;076 cycles, 4.65 bit times btfsc PORTC,RC5 ;077 cycles, 4.71 bit times goto RcTo1_1 ;078 cycles, 4.77 bit times btfsc PORTC,RC5 ;079 cycles, 4.83 bit times goto RcTo1_1 ;080 cycles, 4.90 bit times btfsc PORTC,RC5 ;081 cycles, 4.96 bit times goto RcTo1_1 ;082 cycles, 5.02 bit times btfsc PORTC,RC5 ;083 cycles, 5.08 bit times goto RcTo1_1 ;084 cycles, 5.14 bit times btfsc PORTC,RC5 ;085 cycles, 5.20 bit times goto RcTo1_1 ;086 cycles, 5.26 bit times btfsc PORTC,RC5 ;087 cycles, 5.32 bit times goto RcTo1_1 ;088 cycles, 5.39 bit times btfsc PORTC,RC5 ;089 cycles, 5.45 bit times goto RcTo1_1 ;090 cycles, 5.51 bit times btfsc PORTC,RC5 ;091 cycles, 5.57 bit times goto RcTo1_0 ;092 cycles, 5.63 bit times btfsc PORTC,RC5 ;093 cycles, 5.69 bit times goto RcTo1_0 ;094 cycles, 5.75 bit times btfsc PORTC,RC5 ;095 cycles, 5.81 bit times goto RcTo1_0 ;096 cycles, 5.88 bit times btfsc PORTC,RC5 ;097 cycles, 5.94 bit times goto RcTo1_0 ;098 cycles, 6.00 bit times btfsc PORTC,RC5 ;099 cycles, 6.06 bit times goto RcTo1_0 ;100 cycles, 6.12 bit times btfsc PORTC,RC5 ;101 cycles, 6.18 bit times goto RcTo1_0 ;102 cycles, 6.24 bit times btfsc PORTC,RC5 ;103 cycles, 6.30 bit times goto RcTo1_0 ;104 cycles, 6.36 bit times btfsc PORTC,RC5 ;105 cycles, 6.43 bit times goto RcTo1_0 ;106 cycles, 6.49 bit times btfss PORTA,RA1 ;107 cycles, 6.55 bit times bcf INDF0,7 ;108 cycles, 6.61 bit times addfsr FSR0,1 ;109 cycles, 6.67 bit times goto RcSt0 ;110 cycles, 6.73 bit times RcTo0_5 movlw B'00100000' ;003 cycles, 0.18 bit times iorwf INDF0,F ;004 cycles, 0.24 bit times btfss PORTA,RA1 ;005 cycles, 0.31 bit times bcf INDF0,7 ;006 cycles, 0.37 bit times DNOP ;007-008 cycles, 0.43-0.49 bit times btfsc PORTC,RC5 ;009 cycles, 0.55 bit times goto RcTo1_4 ;010 cycles, 0.61 bit times btfsc PORTC,RC5 ;011 cycles, 0.67 bit times goto RcTo1_4 ;012 cycles, 0.73 bit times btfsc PORTC,RC5 ;013 cycles, 0.80 bit times goto RcTo1_4 ;014 cycles, 0.86 bit times btfsc PORTC,RC5 ;015 cycles, 0.92 bit times goto RcTo1_4 ;016 cycles, 0.98 bit times btfsc PORTC,RC5 ;017 cycles, 1.04 bit times goto RcTo1_4 ;018 cycles, 1.10 bit times btfsc PORTC,RC5 ;019 cycles, 1.16 bit times goto RcTo1_4 ;020 cycles, 1.22 bit times btfsc PORTC,RC5 ;021 cycles, 1.29 bit times goto RcTo1_4 ;022 cycles, 1.35 bit times btfsc PORTC,RC5 ;023 cycles, 1.41 bit times goto RcTo1_4 ;024 cycles, 1.47 bit times btfsc PORTC,RC5 ;025 cycles, 1.53 bit times goto RcTo1_3 ;026 cycles, 1.59 bit times btfsc PORTC,RC5 ;027 cycles, 1.65 bit times goto RcTo1_3 ;028 cycles, 1.71 bit times btfsc PORTC,RC5 ;029 cycles, 1.77 bit times goto RcTo1_3 ;030 cycles, 1.84 bit times btfsc PORTC,RC5 ;031 cycles, 1.90 bit times goto RcTo1_3 ;032 cycles, 1.96 bit times btfsc PORTC,RC5 ;033 cycles, 2.02 bit times goto RcTo1_3 ;034 cycles, 2.08 bit times btfsc PORTC,RC5 ;035 cycles, 2.14 bit times goto RcTo1_3 ;036 cycles, 2.20 bit times btfsc PORTC,RC5 ;037 cycles, 2.26 bit times goto RcTo1_3 ;038 cycles, 2.33 bit times btfsc PORTC,RC5 ;039 cycles, 2.39 bit times goto RcTo1_3 ;040 cycles, 2.45 bit times btfsc PORTC,RC5 ;041 cycles, 2.51 bit times goto RcTo1_2 ;042 cycles, 2.57 bit times btfsc PORTC,RC5 ;043 cycles, 2.63 bit times goto RcTo1_2 ;044 cycles, 2.69 bit times btfsc PORTC,RC5 ;045 cycles, 2.75 bit times goto RcTo1_2 ;046 cycles, 2.82 bit times btfsc PORTC,RC5 ;047 cycles, 2.88 bit times goto RcTo1_2 ;048 cycles, 2.94 bit times btfsc PORTC,RC5 ;049 cycles, 3.00 bit times goto RcTo1_2 ;050 cycles, 3.06 bit times btfsc PORTC,RC5 ;051 cycles, 3.12 bit times goto RcTo1_2 ;052 cycles, 3.18 bit times btfsc PORTC,RC5 ;053 cycles, 3.24 bit times goto RcTo1_2 ;054 cycles, 3.30 bit times btfsc PORTC,RC5 ;055 cycles, 3.37 bit times goto RcTo1_2 ;056 cycles, 3.43 bit times btfsc PORTC,RC5 ;057 cycles, 3.49 bit times goto RcTo1_2 ;058 cycles, 3.55 bit times btfsc PORTC,RC5 ;059 cycles, 3.61 bit times goto RcTo1_1 ;060 cycles, 3.67 bit times btfsc PORTC,RC5 ;061 cycles, 3.73 bit times goto RcTo1_1 ;062 cycles, 3.79 bit times btfsc PORTC,RC5 ;063 cycles, 3.86 bit times goto RcTo1_1 ;064 cycles, 3.92 bit times btfsc PORTC,RC5 ;065 cycles, 3.98 bit times goto RcTo1_1 ;066 cycles, 4.04 bit times btfsc PORTC,RC5 ;067 cycles, 4.10 bit times goto RcTo1_1 ;068 cycles, 4.16 bit times btfsc PORTC,RC5 ;069 cycles, 4.22 bit times goto RcTo1_1 ;070 cycles, 4.28 bit times btfsc PORTC,RC5 ;071 cycles, 4.35 bit times goto RcTo1_1 ;072 cycles, 4.41 bit times btfsc PORTC,RC5 ;073 cycles, 4.47 bit times goto RcTo1_1 ;074 cycles, 4.53 bit times btfsc PORTC,RC5 ;075 cycles, 4.59 bit times goto RcTo1_0 ;076 cycles, 4.65 bit times btfsc PORTC,RC5 ;077 cycles, 4.71 bit times goto RcTo1_0 ;078 cycles, 4.77 bit times btfsc PORTC,RC5 ;079 cycles, 4.83 bit times goto RcTo1_0 ;080 cycles, 4.90 bit times btfsc PORTC,RC5 ;081 cycles, 4.96 bit times goto RcTo1_0 ;082 cycles, 5.02 bit times btfsc PORTC,RC5 ;083 cycles, 5.08 bit times goto RcTo1_0 ;084 cycles, 5.14 bit times btfsc PORTC,RC5 ;085 cycles, 5.20 bit times goto RcTo1_0 ;086 cycles, 5.26 bit times btfsc PORTC,RC5 ;087 cycles, 5.32 bit times goto RcTo1_0 ;088 cycles, 5.39 bit times btfsc PORTC,RC5 ;089 cycles, 5.45 bit times goto RcTo1_0 ;090 cycles, 5.51 bit times btfss PORTA,RA1 ;091 cycles, 5.57 bit times bcf INDF0,7 ;092 cycles, 5.63 bit times addfsr FSR0,1 ;093 cycles, 5.69 bit times goto RcSt0 ;094 cycles, 5.75 bit times RcTo0_4 movlw B'00010000' ;003 cycles, 0.18 bit times iorwf INDF0,F ;004 cycles, 0.24 bit times btfss PORTA,RA1 ;005 cycles, 0.31 bit times bcf INDF0,7 ;006 cycles, 0.37 bit times DNOP ;007-008 cycles, 0.43-0.49 bit times btfsc PORTC,RC5 ;009 cycles, 0.55 bit times goto RcTo1_3 ;010 cycles, 0.61 bit times btfsc PORTC,RC5 ;011 cycles, 0.67 bit times goto RcTo1_3 ;012 cycles, 0.73 bit times btfsc PORTC,RC5 ;013 cycles, 0.80 bit times goto RcTo1_3 ;014 cycles, 0.86 bit times btfsc PORTC,RC5 ;015 cycles, 0.92 bit times goto RcTo1_3 ;016 cycles, 0.98 bit times btfsc PORTC,RC5 ;017 cycles, 1.04 bit times goto RcTo1_3 ;018 cycles, 1.10 bit times btfsc PORTC,RC5 ;019 cycles, 1.16 bit times goto RcTo1_3 ;020 cycles, 1.22 bit times btfsc PORTC,RC5 ;021 cycles, 1.29 bit times goto RcTo1_3 ;022 cycles, 1.35 bit times btfsc PORTC,RC5 ;023 cycles, 1.41 bit times goto RcTo1_3 ;024 cycles, 1.47 bit times btfsc PORTC,RC5 ;025 cycles, 1.53 bit times goto RcTo1_2 ;026 cycles, 1.59 bit times btfsc PORTC,RC5 ;027 cycles, 1.65 bit times goto RcTo1_2 ;028 cycles, 1.71 bit times btfsc PORTC,RC5 ;029 cycles, 1.77 bit times goto RcTo1_2 ;030 cycles, 1.84 bit times btfsc PORTC,RC5 ;031 cycles, 1.90 bit times goto RcTo1_2 ;032 cycles, 1.96 bit times btfsc PORTC,RC5 ;033 cycles, 2.02 bit times goto RcTo1_2 ;034 cycles, 2.08 bit times btfsc PORTC,RC5 ;035 cycles, 2.14 bit times goto RcTo1_2 ;036 cycles, 2.20 bit times btfsc PORTC,RC5 ;037 cycles, 2.26 bit times goto RcTo1_2 ;038 cycles, 2.33 bit times btfsc PORTC,RC5 ;039 cycles, 2.39 bit times goto RcTo1_2 ;040 cycles, 2.45 bit times btfsc PORTC,RC5 ;041 cycles, 2.51 bit times goto RcTo1_1 ;042 cycles, 2.57 bit times btfsc PORTC,RC5 ;043 cycles, 2.63 bit times goto RcTo1_1 ;044 cycles, 2.69 bit times btfsc PORTC,RC5 ;045 cycles, 2.75 bit times goto RcTo1_1 ;046 cycles, 2.82 bit times btfsc PORTC,RC5 ;047 cycles, 2.88 bit times goto RcTo1_1 ;048 cycles, 2.94 bit times btfsc PORTC,RC5 ;049 cycles, 3.00 bit times goto RcTo1_1 ;050 cycles, 3.06 bit times btfsc PORTC,RC5 ;051 cycles, 3.12 bit times goto RcTo1_1 ;052 cycles, 3.18 bit times btfsc PORTC,RC5 ;053 cycles, 3.24 bit times goto RcTo1_1 ;054 cycles, 3.30 bit times btfsc PORTC,RC5 ;055 cycles, 3.37 bit times goto RcTo1_1 ;056 cycles, 3.43 bit times btfsc PORTC,RC5 ;057 cycles, 3.49 bit times goto RcTo1_1 ;058 cycles, 3.55 bit times btfsc PORTC,RC5 ;059 cycles, 3.61 bit times goto RcTo1_0 ;060 cycles, 3.67 bit times btfsc PORTC,RC5 ;061 cycles, 3.73 bit times goto RcTo1_0 ;062 cycles, 3.79 bit times btfsc PORTC,RC5 ;063 cycles, 3.86 bit times goto RcTo1_0 ;064 cycles, 3.92 bit times btfsc PORTC,RC5 ;065 cycles, 3.98 bit times goto RcTo1_0 ;066 cycles, 4.04 bit times btfsc PORTC,RC5 ;067 cycles, 4.10 bit times goto RcTo1_0 ;068 cycles, 4.16 bit times btfsc PORTC,RC5 ;069 cycles, 4.22 bit times goto RcTo1_0 ;070 cycles, 4.28 bit times btfsc PORTC,RC5 ;071 cycles, 4.35 bit times goto RcTo1_0 ;072 cycles, 4.41 bit times btfsc PORTC,RC5 ;073 cycles, 4.47 bit times goto RcTo1_0 ;074 cycles, 4.53 bit times btfss PORTA,RA1 ;075 cycles, 4.59 bit times bcf INDF0,7 ;076 cycles, 4.65 bit times addfsr FSR0,1 ;077 cycles, 4.71 bit times goto RcSt0 ;078 cycles, 4.77 bit times RcTo0_3 movlw B'00001000' ;003 cycles, 0.18 bit times iorwf INDF0,F ;004 cycles, 0.24 bit times btfss PORTA,RA1 ;005 cycles, 0.31 bit times bcf INDF0,7 ;006 cycles, 0.37 bit times DNOP ;007-008 cycles, 0.43-0.49 bit times btfsc PORTC,RC5 ;009 cycles, 0.55 bit times goto RcTo1_2 ;010 cycles, 0.61 bit times btfsc PORTC,RC5 ;011 cycles, 0.67 bit times goto RcTo1_2 ;012 cycles, 0.73 bit times btfsc PORTC,RC5 ;013 cycles, 0.80 bit times goto RcTo1_2 ;014 cycles, 0.86 bit times btfsc PORTC,RC5 ;015 cycles, 0.92 bit times goto RcTo1_2 ;016 cycles, 0.98 bit times btfsc PORTC,RC5 ;017 cycles, 1.04 bit times goto RcTo1_2 ;018 cycles, 1.10 bit times btfsc PORTC,RC5 ;019 cycles, 1.16 bit times goto RcTo1_2 ;020 cycles, 1.22 bit times btfsc PORTC,RC5 ;021 cycles, 1.29 bit times goto RcTo1_2 ;022 cycles, 1.35 bit times btfsc PORTC,RC5 ;023 cycles, 1.41 bit times goto RcTo1_2 ;024 cycles, 1.47 bit times btfsc PORTC,RC5 ;025 cycles, 1.53 bit times goto RcTo1_1 ;026 cycles, 1.59 bit times btfsc PORTC,RC5 ;027 cycles, 1.65 bit times goto RcTo1_1 ;028 cycles, 1.71 bit times btfsc PORTC,RC5 ;029 cycles, 1.77 bit times goto RcTo1_1 ;030 cycles, 1.84 bit times btfsc PORTC,RC5 ;031 cycles, 1.90 bit times goto RcTo1_1 ;032 cycles, 1.96 bit times btfsc PORTC,RC5 ;033 cycles, 2.02 bit times goto RcTo1_1 ;034 cycles, 2.08 bit times btfsc PORTC,RC5 ;035 cycles, 2.14 bit times goto RcTo1_1 ;036 cycles, 2.20 bit times btfsc PORTC,RC5 ;037 cycles, 2.26 bit times goto RcTo1_1 ;038 cycles, 2.33 bit times btfsc PORTC,RC5 ;039 cycles, 2.39 bit times goto RcTo1_1 ;040 cycles, 2.45 bit times btfsc PORTC,RC5 ;041 cycles, 2.51 bit times goto RcTo1_0 ;042 cycles, 2.57 bit times btfsc PORTC,RC5 ;043 cycles, 2.63 bit times goto RcTo1_0 ;044 cycles, 2.69 bit times btfsc PORTC,RC5 ;045 cycles, 2.75 bit times goto RcTo1_0 ;046 cycles, 2.82 bit times btfsc PORTC,RC5 ;047 cycles, 2.88 bit times goto RcTo1_0 ;048 cycles, 2.94 bit times btfsc PORTC,RC5 ;049 cycles, 3.00 bit times goto RcTo1_0 ;050 cycles, 3.06 bit times btfsc PORTC,RC5 ;051 cycles, 3.12 bit times goto RcTo1_0 ;052 cycles, 3.18 bit times btfsc PORTC,RC5 ;053 cycles, 3.24 bit times goto RcTo1_0 ;054 cycles, 3.30 bit times btfsc PORTC,RC5 ;055 cycles, 3.37 bit times goto RcTo1_0 ;056 cycles, 3.43 bit times btfsc PORTC,RC5 ;057 cycles, 3.49 bit times goto RcTo1_0 ;058 cycles, 3.55 bit times btfss PORTA,RA1 ;059 cycles, 3.61 bit times bcf INDF0,7 ;060 cycles, 3.67 bit times addfsr FSR0,1 ;061 cycles, 3.73 bit times goto RcSt0 ;062 cycles, 3.79 bit times RcTo0_2 movlw B'00000100' ;003 cycles, 0.18 bit times iorwf INDF0,F ;004 cycles, 0.24 bit times btfss PORTA,RA1 ;005 cycles, 0.31 bit times bcf INDF0,7 ;006 cycles, 0.37 bit times DNOP ;007-008 cycles, 0.43-0.49 bit times btfsc PORTC,RC5 ;009 cycles, 0.55 bit times goto RcTo1_1 ;010 cycles, 0.61 bit times btfsc PORTC,RC5 ;011 cycles, 0.67 bit times goto RcTo1_1 ;012 cycles, 0.73 bit times btfsc PORTC,RC5 ;013 cycles, 0.80 bit times goto RcTo1_1 ;014 cycles, 0.86 bit times btfsc PORTC,RC5 ;015 cycles, 0.92 bit times goto RcTo1_1 ;016 cycles, 0.98 bit times btfsc PORTC,RC5 ;017 cycles, 1.04 bit times goto RcTo1_1 ;018 cycles, 1.10 bit times btfsc PORTC,RC5 ;019 cycles, 1.16 bit times goto RcTo1_1 ;020 cycles, 1.22 bit times btfsc PORTC,RC5 ;021 cycles, 1.29 bit times goto RcTo1_1 ;022 cycles, 1.35 bit times btfsc PORTC,RC5 ;023 cycles, 1.41 bit times goto RcTo1_1 ;024 cycles, 1.47 bit times btfsc PORTC,RC5 ;025 cycles, 1.53 bit times goto RcTo1_0 ;026 cycles, 1.59 bit times btfsc PORTC,RC5 ;027 cycles, 1.65 bit times goto RcTo1_0 ;028 cycles, 1.71 bit times btfsc PORTC,RC5 ;029 cycles, 1.77 bit times goto RcTo1_0 ;030 cycles, 1.84 bit times btfsc PORTC,RC5 ;031 cycles, 1.90 bit times goto RcTo1_0 ;032 cycles, 1.96 bit times btfsc PORTC,RC5 ;033 cycles, 2.02 bit times goto RcTo1_0 ;034 cycles, 2.08 bit times btfsc PORTC,RC5 ;035 cycles, 2.14 bit times goto RcTo1_0 ;036 cycles, 2.20 bit times btfsc PORTC,RC5 ;037 cycles, 2.26 bit times goto RcTo1_0 ;038 cycles, 2.33 bit times btfsc PORTC,RC5 ;039 cycles, 2.39 bit times goto RcTo1_0 ;040 cycles, 2.45 bit times btfss PORTA,RA1 ;041 cycles, 2.51 bit times bcf INDF0,7 ;042 cycles, 2.57 bit times addfsr FSR0,1 ;043 cycles, 2.63 bit times goto RcSt0 ;044 cycles, 2.69 bit times RcTo0_1 movlw B'00000010' ;003 cycles, 0.18 bit times iorwf INDF0,F ;004 cycles, 0.24 bit times btfss PORTA,RA1 ;005 cycles, 0.31 bit times bcf INDF0,7 ;006 cycles, 0.37 bit times DNOP ;007-008 cycles, 0.43-0.49 bit times btfsc PORTC,RC5 ;009 cycles, 0.55 bit times goto RcTo1_0 ;010 cycles, 0.61 bit times btfsc PORTC,RC5 ;011 cycles, 0.67 bit times goto RcTo1_0 ;012 cycles, 0.73 bit times btfsc PORTC,RC5 ;013 cycles, 0.80 bit times goto RcTo1_0 ;014 cycles, 0.86 bit times btfsc PORTC,RC5 ;015 cycles, 0.92 bit times goto RcTo1_0 ;016 cycles, 0.98 bit times btfsc PORTC,RC5 ;017 cycles, 1.04 bit times goto RcTo1_0 ;018 cycles, 1.10 bit times btfsc PORTC,RC5 ;019 cycles, 1.16 bit times goto RcTo1_0 ;020 cycles, 1.22 bit times btfsc PORTC,RC5 ;021 cycles, 1.29 bit times goto RcTo1_0 ;022 cycles, 1.35 bit times btfsc PORTC,RC5 ;023 cycles, 1.41 bit times goto RcTo1_0 ;024 cycles, 1.47 bit times btfss PORTA,RA1 ;025 cycles, 1.53 bit times bcf INDF0,7 ;026 cycles, 1.59 bit times addfsr FSR0,1 ;027 cycles, 1.65 bit times goto RcSt0 ;028 cycles, 1.71 bit times RcTo0_0 movlw B'00000001' ;003 cycles, 0.18 bit times iorwf INDF0,F ;004 cycles, 0.24 bit times btfss PORTA,RA1 ;005 cycles, 0.31 bit times bcf INDF0,7 ;006 cycles, 0.37 bit times addfsr FSR0,1 ;007 cycles, 0.43 bit times goto RcSt0 ;008 cycles, 0.49 bit times ;;; Received Data Decoder ;;; RecvDecode movf RC_CMDG,W ;Trust the group count that mac sent is andlw B'01111111' ; accurate and copy it into the group count movwf GROUPS ; variable that we return as well as a temp var movwf TEMP2 ; that we can trash movlw 0x20 ;Start both pointers after the three initial movwf FSR0H ; IWM bytes (the sync byte, the length of the movwf FSR1H ; message in groups plus 0x80, the length of movlw 0x4B ; the expected reply in groups plus 0x80) movwf FSR0L ; " movwf FSR1L ; " RDLoop btfss INDF0,7 ;If the MSB of the next byte is clear, we went bra RDSus_7 ; into suspend here, switch loops moviw FSR0++ ;Pick up the byte with the LSBs of the next movwf TEMP ; seven btfss INDF0,7 ;If the MSB of the next byte is clear, we went bra RDSus_6 ; into suspend here, switch loops lsrf TEMP,F ;Rotate the LSB of the first byte of the group rlf INDF0,W ; into place movwi FSR1++ ;Write the restored byte to memory addfsr FSR0,1 ;Advance the input pointer btfss INDF0,7 ;If the MSB of the next byte is clear, we went bra RDSus_5 ; into suspend here, switch loops lsrf TEMP,F ;Rotate the LSB of the second byte of the group rlf INDF0,W ; into place movwi FSR1++ ;Write the restored byte to memory addfsr FSR0,1 ;Advance the input pointer btfss INDF0,7 ;If the MSB of the next byte is clear, we went bra RDSus_4 ; into suspend here, switch loops lsrf TEMP,F ;Rotate the LSB of the third byte of the group rlf INDF0,W ; into place movwi FSR1++ ;Write the restored byte to memory addfsr FSR0,1 ;Advance the input pointer btfss INDF0,7 ;If the MSB of the next byte is clear, we went bra RDSus_3 ; into suspend here, switch loops lsrf TEMP,F ;Rotate the LSB of the fourth byte of the group rlf INDF0,W ; into place movwi FSR1++ ;Write the restored byte to memory addfsr FSR0,1 ;Advance the input pointer btfss INDF0,7 ;If the MSB of the next byte is clear, we went bra RDSus_2 ; into suspend here, switch loops lsrf TEMP,F ;Rotate the LSB of the fifth byte of the group rlf INDF0,W ; into place movwi FSR1++ ;Write the restored byte to memory addfsr FSR0,1 ;Advance the input pointer btfss INDF0,7 ;If the MSB of the next byte is clear, we went bra RDSus_1 ; into suspend here, switch loops lsrf TEMP,F ;Rotate the LSB of the sixth byte of the group rlf INDF0,W ; into place movwi FSR1++ ;Write the restored byte to memory addfsr FSR0,1 ;Advance the input pointer btfss INDF0,7 ;If the MSB of the next byte is clear, we went bra RDSus_0 ; into suspend here, switch loops lsrf TEMP,F ;Rotate the LSB of the last byte of the group rlf INDF0,W ; into place movwi FSR1++ ;Write the restored byte to memory addfsr FSR0,1 ;Advance the input pointer decfsz TEMP2,F ;Decrement the group count and loop if it's not bra RDLoop ; yet zero return RDSus_7 moviw FSR0++ ;Pick up the byte with the LSBs of the next movwf TEMP ; seven RDSus_6 lsrf TEMP,F ;Rotate the LSB of the first byte of the group rlf INDF0,W ; into place movwi FSR1++ ;Write the restored byte to memory addfsr FSR0,1 ;Advance the input pointer RDSus_5 lsrf TEMP,F ;Rotate the LSB of the second byte of the group rlf INDF0,W ; into place movwi FSR1++ ;Write the restored byte to memory addfsr FSR0,1 ;Advance the input pointer RDSus_4 lsrf TEMP,F ;Rotate the LSB of the third byte of the group rlf INDF0,W ; into place movwi FSR1++ ;Write the restored byte to memory addfsr FSR0,1 ;Advance the input pointer RDSus_3 lsrf TEMP,F ;Rotate the LSB of the fourth byte of the group rlf INDF0,W ; into place movwi FSR1++ ;Write the restored byte to memory addfsr FSR0,1 ;Advance the input pointer RDSus_2 lsrf TEMP,F ;Rotate the LSB of the fifth byte of the group rlf INDF0,W ; into place movwi FSR1++ ;Write the restored byte to memory addfsr FSR0,1 ;Advance the input pointer RDSus_1 lsrf TEMP,F ;Rotate the LSB of the sixth byte of the group rlf INDF0,W ; into place movwi FSR1++ ;Write the restored byte to memory addfsr FSR0,1 ;Advance the input pointer RDSus_0 lsrf TEMP,F ;Rotate the LSB of the last byte of the group rlf INDF0,W ; into place movwi FSR1++ ;Write the restored byte to memory addfsr FSR0,1 ;Advance the input pointer decf TEMP2,F ;Decrement the group count btfsc STATUS,Z ;If the group count happens to be zero, mac return ; suspended in the last group and we're done RDSusLp moviw FSR0++ ;Read the next byte, and if it's a sync byte, xorlw 0xAA ; continue processing data btfsc STATUS,Z ; " bra RDLoop ; " btfss FSR0H,2 ;As a safety measure, check if we've gone off bra RDSusLp ; the edge of linear memory before we loop bsf FLAGS,ABORTED ; to check the next byte; if we have, set the return ; aborted flag and return ;;; CRC Lookup Tables ;;; org 0x1D00 LutCrc7 retlw 0x00 retlw 0x12 retlw 0x24 retlw 0x36 retlw 0x48 retlw 0x5A retlw 0x6C retlw 0x7E retlw 0x90 retlw 0x82 retlw 0xB4 retlw 0xA6 retlw 0xD8 retlw 0xCA retlw 0xFC retlw 0xEE retlw 0x32 retlw 0x20 retlw 0x16 retlw 0x04 retlw 0x7A retlw 0x68 retlw 0x5E retlw 0x4C retlw 0xA2 retlw 0xB0 retlw 0x86 retlw 0x94 retlw 0xEA retlw 0xF8 retlw 0xCE retlw 0xDC retlw 0x64 retlw 0x76 retlw 0x40 retlw 0x52 retlw 0x2C retlw 0x3E retlw 0x08 retlw 0x1A retlw 0xF4 retlw 0xE6 retlw 0xD0 retlw 0xC2 retlw 0xBC retlw 0xAE retlw 0x98 retlw 0x8A retlw 0x56 retlw 0x44 retlw 0x72 retlw 0x60 retlw 0x1E retlw 0x0C retlw 0x3A retlw 0x28 retlw 0xC6 retlw 0xD4 retlw 0xE2 retlw 0xF0 retlw 0x8E retlw 0x9C retlw 0xAA retlw 0xB8 retlw 0xC8 retlw 0xDA retlw 0xEC retlw 0xFE retlw 0x80 retlw 0x92 retlw 0xA4 retlw 0xB6 retlw 0x58 retlw 0x4A retlw 0x7C retlw 0x6E retlw 0x10 retlw 0x02 retlw 0x34 retlw 0x26 retlw 0xFA retlw 0xE8 retlw 0xDE retlw 0xCC retlw 0xB2 retlw 0xA0 retlw 0x96 retlw 0x84 retlw 0x6A retlw 0x78 retlw 0x4E retlw 0x5C retlw 0x22 retlw 0x30 retlw 0x06 retlw 0x14 retlw 0xAC retlw 0xBE retlw 0x88 retlw 0x9A retlw 0xE4 retlw 0xF6 retlw 0xC0 retlw 0xD2 retlw 0x3C retlw 0x2E retlw 0x18 retlw 0x0A retlw 0x74 retlw 0x66 retlw 0x50 retlw 0x42 retlw 0x9E retlw 0x8C retlw 0xBA retlw 0xA8 retlw 0xD6 retlw 0xC4 retlw 0xF2 retlw 0xE0 retlw 0x0E retlw 0x1C retlw 0x2A retlw 0x38 retlw 0x46 retlw 0x54 retlw 0x62 retlw 0x70 retlw 0x82 retlw 0x90 retlw 0xA6 retlw 0xB4 retlw 0xCA retlw 0xD8 retlw 0xEE retlw 0xFC retlw 0x12 retlw 0x00 retlw 0x36 retlw 0x24 retlw 0x5A retlw 0x48 retlw 0x7E retlw 0x6C retlw 0xB0 retlw 0xA2 retlw 0x94 retlw 0x86 retlw 0xF8 retlw 0xEA retlw 0xDC retlw 0xCE retlw 0x20 retlw 0x32 retlw 0x04 retlw 0x16 retlw 0x68 retlw 0x7A retlw 0x4C retlw 0x5E retlw 0xE6 retlw 0xF4 retlw 0xC2 retlw 0xD0 retlw 0xAE retlw 0xBC retlw 0x8A retlw 0x98 retlw 0x76 retlw 0x64 retlw 0x52 retlw 0x40 retlw 0x3E retlw 0x2C retlw 0x1A retlw 0x08 retlw 0xD4 retlw 0xC6 retlw 0xF0 retlw 0xE2 retlw 0x9C retlw 0x8E retlw 0xB8 retlw 0xAA retlw 0x44 retlw 0x56 retlw 0x60 retlw 0x72 retlw 0x0C retlw 0x1E retlw 0x28 retlw 0x3A retlw 0x4A retlw 0x58 retlw 0x6E retlw 0x7C retlw 0x02 retlw 0x10 retlw 0x26 retlw 0x34 retlw 0xDA retlw 0xC8 retlw 0xFE retlw 0xEC retlw 0x92 retlw 0x80 retlw 0xB6 retlw 0xA4 retlw 0x78 retlw 0x6A retlw 0x5C retlw 0x4E retlw 0x30 retlw 0x22 retlw 0x14 retlw 0x06 retlw 0xE8 retlw 0xFA retlw 0xCC retlw 0xDE retlw 0xA0 retlw 0xB2 retlw 0x84 retlw 0x96 retlw 0x2E retlw 0x3C retlw 0x0A retlw 0x18 retlw 0x66 retlw 0x74 retlw 0x42 retlw 0x50 retlw 0xBE retlw 0xAC retlw 0x9A retlw 0x88 retlw 0xF6 retlw 0xE4 retlw 0xD2 retlw 0xC0 retlw 0x1C retlw 0x0E retlw 0x38 retlw 0x2A retlw 0x54 retlw 0x46 retlw 0x70 retlw 0x62 retlw 0x8C retlw 0x9E retlw 0xA8 retlw 0xBA retlw 0xC4 retlw 0xD6 retlw 0xE0 retlw 0xF2 org 0x1E00 LutCrc16H retlw 0x00 retlw 0x10 retlw 0x20 retlw 0x30 retlw 0x40 retlw 0x50 retlw 0x60 retlw 0x70 retlw 0x81 retlw 0x91 retlw 0xA1 retlw 0xB1 retlw 0xC1 retlw 0xD1 retlw 0xE1 retlw 0xF1 retlw 0x12 retlw 0x02 retlw 0x32 retlw 0x22 retlw 0x52 retlw 0x42 retlw 0x72 retlw 0x62 retlw 0x93 retlw 0x83 retlw 0xB3 retlw 0xA3 retlw 0xD3 retlw 0xC3 retlw 0xF3 retlw 0xE3 retlw 0x24 retlw 0x34 retlw 0x04 retlw 0x14 retlw 0x64 retlw 0x74 retlw 0x44 retlw 0x54 retlw 0xA5 retlw 0xB5 retlw 0x85 retlw 0x95 retlw 0xE5 retlw 0xF5 retlw 0xC5 retlw 0xD5 retlw 0x36 retlw 0x26 retlw 0x16 retlw 0x06 retlw 0x76 retlw 0x66 retlw 0x56 retlw 0x46 retlw 0xB7 retlw 0xA7 retlw 0x97 retlw 0x87 retlw 0xF7 retlw 0xE7 retlw 0xD7 retlw 0xC7 retlw 0x48 retlw 0x58 retlw 0x68 retlw 0x78 retlw 0x08 retlw 0x18 retlw 0x28 retlw 0x38 retlw 0xC9 retlw 0xD9 retlw 0xE9 retlw 0xF9 retlw 0x89 retlw 0x99 retlw 0xA9 retlw 0xB9 retlw 0x5A retlw 0x4A retlw 0x7A retlw 0x6A retlw 0x1A retlw 0x0A retlw 0x3A retlw 0x2A retlw 0xDB retlw 0xCB retlw 0xFB retlw 0xEB retlw 0x9B retlw 0x8B retlw 0xBB retlw 0xAB retlw 0x6C retlw 0x7C retlw 0x4C retlw 0x5C retlw 0x2C retlw 0x3C retlw 0x0C retlw 0x1C retlw 0xED retlw 0xFD retlw 0xCD retlw 0xDD retlw 0xAD retlw 0xBD retlw 0x8D retlw 0x9D retlw 0x7E retlw 0x6E retlw 0x5E retlw 0x4E retlw 0x3E retlw 0x2E retlw 0x1E retlw 0x0E retlw 0xFF retlw 0xEF retlw 0xDF retlw 0xCF retlw 0xBF retlw 0xAF retlw 0x9F retlw 0x8F retlw 0x91 retlw 0x81 retlw 0xB1 retlw 0xA1 retlw 0xD1 retlw 0xC1 retlw 0xF1 retlw 0xE1 retlw 0x10 retlw 0x00 retlw 0x30 retlw 0x20 retlw 0x50 retlw 0x40 retlw 0x70 retlw 0x60 retlw 0x83 retlw 0x93 retlw 0xA3 retlw 0xB3 retlw 0xC3 retlw 0xD3 retlw 0xE3 retlw 0xF3 retlw 0x02 retlw 0x12 retlw 0x22 retlw 0x32 retlw 0x42 retlw 0x52 retlw 0x62 retlw 0x72 retlw 0xB5 retlw 0xA5 retlw 0x95 retlw 0x85 retlw 0xF5 retlw 0xE5 retlw 0xD5 retlw 0xC5 retlw 0x34 retlw 0x24 retlw 0x14 retlw 0x04 retlw 0x74 retlw 0x64 retlw 0x54 retlw 0x44 retlw 0xA7 retlw 0xB7 retlw 0x87 retlw 0x97 retlw 0xE7 retlw 0xF7 retlw 0xC7 retlw 0xD7 retlw 0x26 retlw 0x36 retlw 0x06 retlw 0x16 retlw 0x66 retlw 0x76 retlw 0x46 retlw 0x56 retlw 0xD9 retlw 0xC9 retlw 0xF9 retlw 0xE9 retlw 0x99 retlw 0x89 retlw 0xB9 retlw 0xA9 retlw 0x58 retlw 0x48 retlw 0x78 retlw 0x68 retlw 0x18 retlw 0x08 retlw 0x38 retlw 0x28 retlw 0xCB retlw 0xDB retlw 0xEB retlw 0xFB retlw 0x8B retlw 0x9B retlw 0xAB retlw 0xBB retlw 0x4A retlw 0x5A retlw 0x6A retlw 0x7A retlw 0x0A retlw 0x1A retlw 0x2A retlw 0x3A retlw 0xFD retlw 0xED retlw 0xDD retlw 0xCD retlw 0xBD retlw 0xAD retlw 0x9D retlw 0x8D retlw 0x7C retlw 0x6C retlw 0x5C retlw 0x4C retlw 0x3C retlw 0x2C retlw 0x1C retlw 0x0C retlw 0xEF retlw 0xFF retlw 0xCF retlw 0xDF retlw 0xAF retlw 0xBF retlw 0x8F retlw 0x9F retlw 0x6E retlw 0x7E retlw 0x4E retlw 0x5E retlw 0x2E retlw 0x3E retlw 0x0E retlw 0x1E org 0x1F00 LutCrc16L retlw 0x00 retlw 0x21 retlw 0x42 retlw 0x63 retlw 0x84 retlw 0xA5 retlw 0xC6 retlw 0xE7 retlw 0x08 retlw 0x29 retlw 0x4A retlw 0x6B retlw 0x8C retlw 0xAD retlw 0xCE retlw 0xEF retlw 0x31 retlw 0x10 retlw 0x73 retlw 0x52 retlw 0xB5 retlw 0x94 retlw 0xF7 retlw 0xD6 retlw 0x39 retlw 0x18 retlw 0x7B retlw 0x5A retlw 0xBD retlw 0x9C retlw 0xFF retlw 0xDE retlw 0x62 retlw 0x43 retlw 0x20 retlw 0x01 retlw 0xE6 retlw 0xC7 retlw 0xA4 retlw 0x85 retlw 0x6A retlw 0x4B retlw 0x28 retlw 0x09 retlw 0xEE retlw 0xCF retlw 0xAC retlw 0x8D retlw 0x53 retlw 0x72 retlw 0x11 retlw 0x30 retlw 0xD7 retlw 0xF6 retlw 0x95 retlw 0xB4 retlw 0x5B retlw 0x7A retlw 0x19 retlw 0x38 retlw 0xDF retlw 0xFE retlw 0x9D retlw 0xBC retlw 0xC4 retlw 0xE5 retlw 0x86 retlw 0xA7 retlw 0x40 retlw 0x61 retlw 0x02 retlw 0x23 retlw 0xCC retlw 0xED retlw 0x8E retlw 0xAF retlw 0x48 retlw 0x69 retlw 0x0A retlw 0x2B retlw 0xF5 retlw 0xD4 retlw 0xB7 retlw 0x96 retlw 0x71 retlw 0x50 retlw 0x33 retlw 0x12 retlw 0xFD retlw 0xDC retlw 0xBF retlw 0x9E retlw 0x79 retlw 0x58 retlw 0x3B retlw 0x1A retlw 0xA6 retlw 0x87 retlw 0xE4 retlw 0xC5 retlw 0x22 retlw 0x03 retlw 0x60 retlw 0x41 retlw 0xAE retlw 0x8F retlw 0xEC retlw 0xCD retlw 0x2A retlw 0x0B retlw 0x68 retlw 0x49 retlw 0x97 retlw 0xB6 retlw 0xD5 retlw 0xF4 retlw 0x13 retlw 0x32 retlw 0x51 retlw 0x70 retlw 0x9F retlw 0xBE retlw 0xDD retlw 0xFC retlw 0x1B retlw 0x3A retlw 0x59 retlw 0x78 retlw 0x88 retlw 0xA9 retlw 0xCA retlw 0xEB retlw 0x0C retlw 0x2D retlw 0x4E retlw 0x6F retlw 0x80 retlw 0xA1 retlw 0xC2 retlw 0xE3 retlw 0x04 retlw 0x25 retlw 0x46 retlw 0x67 retlw 0xB9 retlw 0x98 retlw 0xFB retlw 0xDA retlw 0x3D retlw 0x1C retlw 0x7F retlw 0x5E retlw 0xB1 retlw 0x90 retlw 0xF3 retlw 0xD2 retlw 0x35 retlw 0x14 retlw 0x77 retlw 0x56 retlw 0xEA retlw 0xCB retlw 0xA8 retlw 0x89 retlw 0x6E retlw 0x4F retlw 0x2C retlw 0x0D retlw 0xE2 retlw 0xC3 retlw 0xA0 retlw 0x81 retlw 0x66 retlw 0x47 retlw 0x24 retlw 0x05 retlw 0xDB retlw 0xFA retlw 0x99 retlw 0xB8 retlw 0x5F retlw 0x7E retlw 0x1D retlw 0x3C retlw 0xD3 retlw 0xF2 retlw 0x91 retlw 0xB0 retlw 0x57 retlw 0x76 retlw 0x15 retlw 0x34 retlw 0x4C retlw 0x6D retlw 0x0E retlw 0x2F retlw 0xC8 retlw 0xE9 retlw 0x8A retlw 0xAB retlw 0x44 retlw 0x65 retlw 0x06 retlw 0x27 retlw 0xC0 retlw 0xE1 retlw 0x82 retlw 0xA3 retlw 0x7D retlw 0x5C retlw 0x3F retlw 0x1E retlw 0xF9 retlw 0xD8 retlw 0xBB retlw 0x9A retlw 0x75 retlw 0x54 retlw 0x37 retlw 0x16 retlw 0xF1 retlw 0xD0 retlw 0xB3 retlw 0x92 retlw 0x2E retlw 0x0F retlw 0x6C retlw 0x4D retlw 0xAA retlw 0x8B retlw 0xE8 retlw 0xC9 retlw 0x26 retlw 0x07 retlw 0x64 retlw 0x45 retlw 0xA2 retlw 0x83 retlw 0xE0 retlw 0xC1 retlw 0x1F retlw 0x3E retlw 0x5D retlw 0x7C retlw 0x9B retlw 0xBA retlw 0xD9 retlw 0xF8 retlw 0x17 retlw 0x36 retlw 0x55 retlw 0x74 retlw 0x93 retlw 0xB2 retlw 0xD1 retlw 0xF0 ;;; End of Program ;;; end