tashtwenty/firmware/tashtwenty.asm
lampmerchant 3144494de5 20211128
2021-11-28 10:29:06 -07:00

4688 lines
156 KiB
NASM

;;; 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 <https://www.gnu.org/licenses/>.
;;; 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