mirror of
https://github.com/lampmerchant/tashtwenty.git
synced 2024-12-30 09:29:21 +00:00
20220424
This commit is contained in:
parent
70cf1e5b88
commit
a49b5b2f1e
@ -90,8 +90,8 @@ IWMCNT0 equ 0 ; "
|
|||||||
M_FAIL equ 7 ;Set when there's been a failure on the MMC interface
|
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_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_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_RDCMD equ 4 ;Set when state machine should do a read command
|
||||||
M_MBWR equ 3 ;Set when a multiblock write is in progress
|
M_ONGWR equ 3 ;Set when state machine shouldn't stop tran on a write
|
||||||
M_BKADR equ 2 ;Set when block (rather than byte) addressing is in use
|
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
|
M_CDVER equ 1 ;Set when dealing with a V2.0+ card, clear for 1.0
|
||||||
|
|
||||||
@ -127,7 +127,7 @@ M_CDVER equ 1 ;Set when dealing with a V2.0+ card, clear for 1.0
|
|||||||
M_ADR0 ;Fourth (low) byte of the address, last byte of R3/R7 response
|
M_ADR0 ;Fourth (low) byte of the address, last byte of R3/R7 response
|
||||||
M_CRCH ;CRC16 high byte
|
M_CRCH ;CRC16 high byte
|
||||||
M_CRCL ;CRC16 low byte
|
M_CRCL ;CRC16 low byte
|
||||||
X6 ;Various purposes
|
M_STATE ;State of card state machine
|
||||||
X5 ;Various purposes
|
X5 ;Various purposes
|
||||||
X4 ;Various purposes
|
X4 ;Various purposes
|
||||||
X3 ;Various purposes
|
X3 ;Various purposes
|
||||||
@ -526,11 +526,9 @@ Unselected
|
|||||||
tris 7 ; done this already, but.. belt and suspenders)
|
tris 7 ; done this already, but.. belt and suspenders)
|
||||||
movlb 3 ;Deassert !HSHK
|
movlb 3 ;Deassert !HSHK
|
||||||
clrf TXREG ; "
|
clrf TXREG ; "
|
||||||
movlb 0 ;Deassert !CS and next !ENBL (the interrupt
|
movlb 0 ;Deassert next !ENBL (the interrupt handler
|
||||||
movlw B'00111111' ; handler will have deasserted next !ENBL
|
movlw B'00111111' ; will have deasserted next !ENBL already,
|
||||||
movwf PORTC ; already, but.. belt and suspenders)
|
movwf PORTA ; but.. belt and suspenders)
|
||||||
movlw B'00111111' ; "
|
|
||||||
movwf PORTA ; "
|
|
||||||
clrf DEVNUM ;Reset selected device number to zero
|
clrf DEVNUM ;Reset selected device number to zero
|
||||||
btfsc EN_PORT,EN_PIN ;Wait for Mac to drive !ENBL low
|
btfsc EN_PORT,EN_PIN ;Wait for Mac to drive !ENBL low
|
||||||
bra $-1 ; "
|
bra $-1 ; "
|
||||||
@ -862,6 +860,16 @@ SysIni6 addfsr FSR0,16 ;Move pop pointer ahead to next entry
|
|||||||
;;; Receiver ;;;
|
;;; Receiver ;;;
|
||||||
|
|
||||||
Receiver
|
Receiver
|
||||||
|
movlw 4 ;Spend about 262.144 ms waiting for the state
|
||||||
|
movwf X1 ; machine to try and get the card back to
|
||||||
|
Receiv0 clrf TMR1H ; waiting for a command or a write token, which
|
||||||
|
clrf TMR1L ; is about how long we have before Mac tires of
|
||||||
|
movlw MSSWrEtTok - MSS; waiting for us to acknowledge a command (we
|
||||||
|
btfss M_FLAGS,M_ONGWR ; actually have ~350 ms, but be cautious);
|
||||||
|
movlw MSSWaitCmd - MSS; hopefully this will be enough, spec says that
|
||||||
|
call MmcWaitState ; writes may take up to 200 ms
|
||||||
|
decfsz X1,F ; "
|
||||||
|
bra Receiv0 ; "
|
||||||
movlb 3 ;Assert !HSHK to signal to Mac that we're
|
movlb 3 ;Assert !HSHK to signal to Mac that we're
|
||||||
btfss TXSTA,TRMT ; ready to receive
|
btfss TXSTA,TRMT ; ready to receive
|
||||||
bra $-1 ; "
|
bra $-1 ; "
|
||||||
@ -1022,25 +1030,22 @@ BadChk1 movlp 0 ;Return to the idle loop
|
|||||||
goto IdleLoop ; "
|
goto IdleLoop ; "
|
||||||
|
|
||||||
CmdRead
|
CmdRead
|
||||||
call MmcStopOngoing ;Make sure any ongoing write is stopped
|
|
||||||
movlw ERRCODE ;Ready an error code in case we need to jump
|
movlw ERRCODE ;Ready an error code in case we need to jump
|
||||||
movwf RESPERR ; into the placeholder response routine
|
movwf RESPERR ; into the placeholder response routine
|
||||||
call SetupCmdAddr ;Set up the card address for this command
|
call SetupCmdAddr ;Set up the card address for this command
|
||||||
btfsc STATUS,C ;If the read is out of bounds, send an error
|
btfsc STATUS,C ;If the read is out of bounds, send an error
|
||||||
goto CmdPlaceholder ; response
|
goto CmdPlaceholder ; response
|
||||||
CmdRea0 movlw 0x51 ;Set up a read command for the card (R1-type
|
CmdRea0 bsf M_FLAGS,M_RDCMD ;Set the state machine to do a read for us
|
||||||
movwf M_CMDN ; response)
|
bcf M_FLAGS,M_ONGWR ;Cancel any ongoing write
|
||||||
bcf M_FLAGS,M_CMDLR ; "
|
movlw 4 ;Spend about 262.144 ms waiting for the state
|
||||||
bcf M_FLAGS,M_CMDRB ; "
|
movwf X1 ; machine to prepare the card to read out the
|
||||||
bcf CS_PORT,CS_PIN ;Assert !CS
|
CmdRea5 clrf TMR1H ; data, which is about how long we have before
|
||||||
call MmcCmd ;Send the read command
|
clrf TMR1L ; Mac tires of waiting for a response from us
|
||||||
movf M_CMDN,W ;Treat any error flag as a failed command
|
movlw MSSRdData - MSS ; (we actually have ~350 ms, but be cautious)
|
||||||
andlw B'11111110' ; "
|
call MmcWaitState ; "
|
||||||
btfss STATUS,Z ; "
|
decfsz X1,F ; "
|
||||||
bsf M_FLAGS,M_FAIL ; "
|
bra CmdRea5 ; "
|
||||||
btfss M_FLAGS,M_FAIL ;If no failures up to this point, prepare the
|
btfsc PIR1,TMR1IF ;If there was any failure, respond with a
|
||||||
call MmcGetData ; card to read out data
|
|
||||||
btfsc M_FLAGS,M_FAIL ;If there was any failure, respond with a
|
|
||||||
goto CmdPlaceholder ; placeholder with an error code
|
goto CmdPlaceholder ; placeholder with an error code
|
||||||
clrf M_CRCH ;Clear the CRC registers for our read of the
|
clrf M_CRCH ;Clear the CRC registers for our read of the
|
||||||
clrf M_CRCL ; block
|
clrf M_CRCL ; block
|
||||||
@ -1082,6 +1087,8 @@ CmdRea2 moviw FSR0++ ;Pick up the next byte to write from the queue
|
|||||||
bra CmdRea2 ; "
|
bra CmdRea2 ; "
|
||||||
decfsz X3,F ; "
|
decfsz X3,F ; "
|
||||||
bra CmdRea2 ; "
|
bra CmdRea2 ; "
|
||||||
|
movlw MSSWaitCmd - MSS;Finished with read, so set state back to
|
||||||
|
movwf M_STATE ; WaitCmd
|
||||||
movf M_CRCH,W ;Feeding the CRC through the CRC registers
|
movf M_CRCH,W ;Feeding the CRC through the CRC registers
|
||||||
iorwf M_CRCL,W ; should leave it at zero if the CRC is right;
|
iorwf M_CRCL,W ; should leave it at zero if the CRC is right;
|
||||||
btfss STATUS,Z ; if it's not, send the wrong checksum so Mac
|
btfss STATUS,Z ; if it's not, send the wrong checksum so Mac
|
||||||
@ -1104,7 +1111,6 @@ CmdRea4 comf CHKSUM,W ;CRC failed, so write what we know is the wrong
|
|||||||
bra CmdRea3
|
bra CmdRea3
|
||||||
|
|
||||||
CmdStatus
|
CmdStatus
|
||||||
call MmcStopOngoing ;Make sure any ongoing write is stopped
|
|
||||||
movlw 0x21 ;Point to the partition information block for
|
movlw 0x21 ;Point to the partition information block for
|
||||||
movwf FSR0H ; the selected device
|
movwf FSR0H ; the selected device
|
||||||
swapf DEVNUM,W ; "
|
swapf DEVNUM,W ; "
|
||||||
@ -1115,26 +1121,24 @@ CmdStatus
|
|||||||
xorlw 0xAF ; built-in icon, not one loaded from the card,
|
xorlw 0xAF ; built-in icon, not one loaded from the card,
|
||||||
btfsc STATUS,Z ; so skip setting up the read
|
btfsc STATUS,Z ; so skip setting up the read
|
||||||
bra CmdSta0 ; "
|
bra CmdSta0 ; "
|
||||||
movlw 0x51 ;Set up a read command for the card (R1-type
|
bsf M_FLAGS,M_RDCMD ;Set the state machine to do a read for us
|
||||||
movwf M_CMDN ; response)
|
bcf M_FLAGS,M_ONGWR ;Cancel any ongoing write
|
||||||
bcf M_FLAGS,M_CMDLR ; "
|
|
||||||
bcf M_FLAGS,M_CMDRB ; "
|
|
||||||
clrf M_ADR3 ;Point to the address of the icon to be loaded
|
clrf M_ADR3 ;Point to the address of the icon to be loaded
|
||||||
clrf M_ADR2 ; "
|
clrf M_ADR2 ; "
|
||||||
clrf M_ADR1 ; "
|
clrf M_ADR1 ; "
|
||||||
moviw 4[FSR0] ; "
|
moviw 4[FSR0] ; "
|
||||||
movwf M_ADR0 ; "
|
movwf M_ADR0 ; "
|
||||||
bcf CS_PORT,CS_PIN ;Assert !CS
|
|
||||||
call MmcConvAddr ;Convert address to bytes if necessary
|
call MmcConvAddr ;Convert address to bytes if necessary
|
||||||
btfss M_FLAGS,M_FAIL ;If the address conversion didn't fail, send
|
movlw 4 ;Spend about 262.144 ms waiting for the state
|
||||||
call MmcCmd ; the read command
|
movwf X1 ; machine to prepare the card to read out the
|
||||||
movf M_CMDN,W ;Treat any error flag as a failed command
|
CmdSta8 clrf TMR1H ; icon, which is about how long we have before
|
||||||
andlw B'11111110' ; "
|
clrf TMR1L ; Mac tires of waiting for a response from us
|
||||||
btfss STATUS,Z ; "
|
movlw MSSRdData - MSS ; (we actually have ~350 ms, but be cautious)
|
||||||
bsf M_FLAGS,M_FAIL ; "
|
call MmcWaitState ; "
|
||||||
btfsc M_FLAGS,M_FAIL ;If the operation failed, use the built-in icon
|
decfsz X1,F ; "
|
||||||
bra CmdSta0 ; instead
|
bra CmdSta8 ; "
|
||||||
call MmcGetData ;Get the card ready to read out data
|
btfsc PIR1,TMR1IF ;If it timed out, use the built in icon instead
|
||||||
|
bra CmdSta0 ; "
|
||||||
movlw 0x22 ;Point the push pointer off into space and
|
movlw 0x22 ;Point the push pointer off into space and
|
||||||
movwf FSR1H ; read and throw away the first 256 bytes of
|
movwf FSR1H ; read and throw away the first 256 bytes of
|
||||||
movlw 0 ; the icon sector
|
movlw 0 ; the icon sector
|
||||||
@ -1187,7 +1191,7 @@ CmdSta3 movlw 0 ; area (52 bytes), all as zeroes
|
|||||||
moviw 4[FSR0] ;If the partition type is 0xAF or we had a fail
|
moviw 4[FSR0] ;If the partition type is 0xAF or we had a fail
|
||||||
xorlw 0xAF ; while reading from the card, we're using the
|
xorlw 0xAF ; while reading from the card, we're using the
|
||||||
btfss STATUS,Z ; built-in icon, so skip ahead to do that
|
btfss STATUS,Z ; built-in icon, so skip ahead to do that
|
||||||
btfsc M_FLAGS,M_FAIL ; "
|
btfsc PIR1,TMR1IF ; "
|
||||||
bra CmdSta4 ; "
|
bra CmdSta4 ; "
|
||||||
movlw 0 ;Copy 256 bytes from the card to the Mac
|
movlw 0 ;Copy 256 bytes from the card to the Mac
|
||||||
call MmcCopyData ; "
|
call MmcCopyData ; "
|
||||||
@ -1232,8 +1236,12 @@ CmdSta7 movlw 0 ; area (52 bytes), all as zeroes
|
|||||||
movf CHKSUM,W ;Finish the block off with the checksum
|
movf CHKSUM,W ;Finish the block off with the checksum
|
||||||
call WriteByte ; "
|
call WriteByte ; "
|
||||||
btfss X2,0 ;If we didn't use the built-in icon, finish up
|
btfss X2,0 ;If we didn't use the built-in icon, finish up
|
||||||
call MmcCheckCrc ; with the card by ignoring the CRC
|
call MmcCheckCrc ; with the card by ignoring the CRC and setting
|
||||||
bsf CS_PORT,CS_PIN ;Deassert !CS
|
movlw MSSWaitCmd - MSS; the state back to WaitCmd and deasserting !CS
|
||||||
|
btfss X2,0 ; "
|
||||||
|
movwf M_STATE ; "
|
||||||
|
btfss X2,0 ; "
|
||||||
|
bsf CS_PORT,CS_PIN ; "
|
||||||
call ReturnToIdle ;Return to the idle state
|
call ReturnToIdle ;Return to the idle state
|
||||||
movlp 0 ;Return to the idle loop
|
movlp 0 ;Return to the idle loop
|
||||||
goto IdleLoop ; "
|
goto IdleLoop ; "
|
||||||
@ -1244,8 +1252,12 @@ CmdWrite
|
|||||||
call SetupCmdAddr ;Set up the card address for this command
|
call SetupCmdAddr ;Set up the card address for this command
|
||||||
btfsc STATUS,C ;If the write is out of bounds, send an error
|
btfsc STATUS,C ;If the write is out of bounds, send an error
|
||||||
goto WaitToFinish ; response after we've received the command
|
goto WaitToFinish ; response after we've received the command
|
||||||
btfsc M_FLAGS,M_MBWR ;If we're starting a new write even though a
|
movf M_STATE,W ;If we're not in the await-command state, we
|
||||||
bra CmdWri7 ; multiblock write is ongoing, handle it
|
xorlw MSSWaitCmd - MSS; won't be able to do this write, so send an
|
||||||
|
btfss STATUS,Z ; error response
|
||||||
|
goto WaitToFinish ; "
|
||||||
|
btfsc M_FLAGS,M_ONGWR ;If we're starting a new write even though a
|
||||||
|
bra CmdWri6 ; multiblock write is ongoing, handle it
|
||||||
movlw 0x59 ;Set up a multiblock write command for the card
|
movlw 0x59 ;Set up a multiblock write command for the card
|
||||||
movwf M_CMDN ; (R1-type reply)
|
movwf M_CMDN ; (R1-type reply)
|
||||||
bcf M_FLAGS,M_CMDLR ; "
|
bcf M_FLAGS,M_CMDLR ; "
|
||||||
@ -1258,7 +1270,7 @@ CmdWrite
|
|||||||
bsf M_FLAGS,M_FAIL ; "
|
bsf M_FLAGS,M_FAIL ; "
|
||||||
btfsc M_FLAGS,M_FAIL ;If there was any failure, respond with a
|
btfsc M_FLAGS,M_FAIL ;If there was any failure, respond with a
|
||||||
goto WaitToFinish ; placeholder with an error code
|
goto WaitToFinish ; placeholder with an error code
|
||||||
bsf M_FLAGS,M_MBWR ;Flag that a multiblock write is in progress
|
bsf M_FLAGS,M_ONGWR ;Flag that a multiblock write is in progress
|
||||||
CmdWri0 movlb 4 ;Clock a dummy byte while keeping MOSI high
|
CmdWri0 movlb 4 ;Clock a dummy byte while keeping MOSI high
|
||||||
movlw 0xFF ; "
|
movlw 0xFF ; "
|
||||||
movwf SSP1BUF ; "
|
movwf SSP1BUF ; "
|
||||||
@ -1339,37 +1351,54 @@ CmdWri4 movlb 4 ;Clock the byte out to the card
|
|||||||
bra $-1 ; "
|
bra $-1 ; "
|
||||||
movf SSP1BUF,W ;Save data response to check later
|
movf SSP1BUF,W ;Save data response to check later
|
||||||
movwf X2 ; "
|
movwf X2 ; "
|
||||||
call MmcWaitBusy ;Wait for the card not to be busy anymore
|
movlw 0xFF ;Start clocking the first is-still-busy? byte
|
||||||
movlb 0 ;If the data response byte indicated that the
|
movwf SSP1BUF ; "
|
||||||
movf X2,W ; write succeeded, skip ahead
|
movlb 0 ; "
|
||||||
|
bcf PIR1,SSP1IF ;Clear SSP int flag so it knows when not busy
|
||||||
|
movlw MSSWrBusy - MSS ;Set the card state to WrBusy so state machine
|
||||||
|
movwf M_STATE ; knows
|
||||||
|
decf CMDCNT,W ;If this was the last block, clear the ongoing
|
||||||
|
btfsc STATUS,Z ; write flag so state machine knows not to stop
|
||||||
|
bcf M_FLAGS,M_ONGWR ; waiting on a write or stop tran token
|
||||||
|
movf X2,W ;Check if the write succeeded
|
||||||
andlw B'00011111' ; "
|
andlw B'00011111' ; "
|
||||||
xorlw B'00000101' ; "
|
xorlw B'00000101' ; "
|
||||||
btfsc STATUS,Z ; "
|
btfsc STATUS,Z ;If it did, clear the error flag so we send a
|
||||||
bra CmdWri6 ; "
|
clrf RESPERR ; success response
|
||||||
CmdWri5 call MmcStopOngoing ;Stop the ongoing write
|
btfss STATUS,Z ;If it didn't, clear the ongoing write flag so
|
||||||
btfss IWMFLAG,IWMOVER ;Wait until the Mac's transmission is over
|
bcf M_FLAGS,M_ONGWR ; the write ends here
|
||||||
|
CmdWri5 btfss IWMFLAG,IWMOVER ;Wait until the Mac's transmission is over
|
||||||
bra $-1 ; "
|
bra $-1 ; "
|
||||||
call ReturnToIdle ;If the checksum was wrong, send a NAK, if it
|
movf CHKSUM,W ;If the checksum didn't match, clear the
|
||||||
movf CHKSUM,W ; was right, send an error
|
btfss STATUS,Z ; ongoing write flag because the write stops
|
||||||
btfss STATUS,Z ; "
|
bcf M_FLAGS,M_ONGWR ; here
|
||||||
goto BadChecksum ; "
|
clrf TMR1H ;Spend about 65.536 ms, which is about how long
|
||||||
|
clrf TMR1L ; we have before Mac timeouts waiting for us to
|
||||||
|
movlw MSSWrEtTok - MSS; return to idle, waiting for the state machine
|
||||||
|
btfss M_FLAGS,M_ONGWR ; to try and get the card back to waiting for
|
||||||
|
movlw MSSWaitCmd - MSS; a command or a write token (we actually have
|
||||||
|
call MmcWaitState ; ~90 ms, but let's be cautious)
|
||||||
|
call ReturnToIdle ;That's long enough, return us to idle
|
||||||
|
movf CHKSUM,W ;If the checksum was wrong, send a NAK, else
|
||||||
|
btfss STATUS,Z ; send either a failure or success depending
|
||||||
|
goto BadChecksum ; on RESPERR
|
||||||
goto CmdPlaceholder ; "
|
goto CmdPlaceholder ; "
|
||||||
CmdWri6 decf CMDCNT,W ;If this was the last block in the write, stop
|
CmdWri6 movlw 1 ;In the unlikely event Mac tried to start a new
|
||||||
btfsc STATUS,Z ; the ongoing write
|
|
||||||
call MmcStopOngoing ; "
|
|
||||||
clrf RESPERR ;Send a success response
|
|
||||||
call ReturnToIdle ; "
|
|
||||||
goto CmdPlaceholder ; "
|
|
||||||
CmdWri7 movlw 1 ;In the unlikely event Mac tried to start a new
|
|
||||||
movwf CHKSUM ; write while one was ongoing, pretend there
|
movwf CHKSUM ; write while one was ongoing, pretend there
|
||||||
bra CmdWri5 ; was a bad checksum so it tries again
|
bra CmdWri5 ; was a bad checksum so it tries again
|
||||||
|
|
||||||
CmdWriteCont
|
CmdWriteCont
|
||||||
movlw ERRCODE ;Ready an error code in case we need to jump
|
movlw ERRCODE ;Ready an error code in case we need to jump
|
||||||
movwf RESPERR ; into the placeholder response routine
|
movwf RESPERR ; into the placeholder response routine
|
||||||
btfsc M_FLAGS,M_MBWR ;If a multibyte write is already ongoing, as it
|
btfss M_FLAGS,M_ONGWR ;If a write isn't ongoing as it should be,
|
||||||
bra CmdWri0 ; should be, jump into the middle of CmdWrite,
|
bra CmdWrC0 ; handle this
|
||||||
goto WaitToFinish ; otherwise send an error response
|
movf M_STATE,W ;If we're not in the await-token state, we
|
||||||
|
xorlw MSSWrEtTok - MSS; won't be able to do this write, handle this
|
||||||
|
btfss STATUS,Z ; "
|
||||||
|
bra CmdWrC0 ; "
|
||||||
|
bra CmdWri0 ;Else jump into the middle of CmdWrite
|
||||||
|
CmdWrC0 bcf M_FLAGS,M_ONGWR ;If something went wrong, end the ongoing write
|
||||||
|
goto WaitToFinish ; and send an error response
|
||||||
|
|
||||||
|
|
||||||
;;; Subprograms ;;;
|
;;; Subprograms ;;;
|
||||||
@ -1398,21 +1427,21 @@ SetupCmdAddr
|
|||||||
movlw 0 ; "
|
movlw 0 ; "
|
||||||
addwfc CMDHIGH,W ; "
|
addwfc CMDHIGH,W ; "
|
||||||
movwf M_ADR2 ; "
|
movwf M_ADR2 ; "
|
||||||
moviw 5[FSR0] ;If the partition size is less than or equal to
|
moviw 7[FSR0] ;If the partition size is less than or equal to
|
||||||
subwf M_ADR0,W ; the maximum block number accessed, return
|
subwf M_ADR0,W ; the maximum block number accessed, return
|
||||||
moviw 6[FSR0] ; with carry set
|
moviw 6[FSR0] ; with carry set
|
||||||
subwfb M_ADR1,W ; "
|
subwfb M_ADR1,W ; "
|
||||||
moviw 7[FSR0] ; "
|
moviw 5[FSR0] ; "
|
||||||
subwfb M_ADR2,W ; "
|
subwfb M_ADR2,W ; "
|
||||||
btfsc STATUS,C ; "
|
btfsc STATUS,C ; "
|
||||||
bra SetCmA0 ; "
|
bra SetCmA0 ; "
|
||||||
movf INDF0,W ;Move the starting block of the partition into
|
movf INDF0,W ;Move the starting block of the partition into
|
||||||
movwf M_ADR3 ; the card address registers
|
movwf M_ADR3 ; the card address registers
|
||||||
moviw 1[INDF0] ; "
|
moviw 1[FSR0] ; "
|
||||||
movwf M_ADR2 ; "
|
movwf M_ADR2 ; "
|
||||||
moviw 2[INDF0] ; "
|
moviw 2[FSR0] ; "
|
||||||
movwf M_ADR1 ; "
|
movwf M_ADR1 ; "
|
||||||
moviw 3[INDF0] ; "
|
moviw 3[FSR0] ; "
|
||||||
addwf CMDLOW,W ;Add the block address from the command to it
|
addwf CMDLOW,W ;Add the block address from the command to it
|
||||||
movwf M_ADR0 ; "
|
movwf M_ADR0 ; "
|
||||||
movf CMDMED,W ; "
|
movf CMDMED,W ; "
|
||||||
@ -1587,6 +1616,7 @@ ReqSnd1 bsf STATUS,Z ;We've successfully requested to send, set the
|
|||||||
;Initialize MMC card. Sets M_FAIL on fail. Trashes X0 through X3.
|
;Initialize MMC card. Sets M_FAIL on fail. Trashes X0 through X3.
|
||||||
MmcInit
|
MmcInit
|
||||||
clrf M_FLAGS ;Make sure flags are all clear to begin with
|
clrf M_FLAGS ;Make sure flags are all clear to begin with
|
||||||
|
clrf M_STATE ;Make sure state starts at awaiting command
|
||||||
call MmcIni0 ;Call into the function below
|
call MmcIni0 ;Call into the function below
|
||||||
bsf CS_PORT,CS_PIN ;Always deassert !CS
|
bsf CS_PORT,CS_PIN ;Always deassert !CS
|
||||||
movf WREG,W ;If the init function returned a code other
|
movf WREG,W ;If the init function returned a code other
|
||||||
@ -2055,40 +2085,206 @@ MmcChe0 movlw 0xFF ;Clock the low CRC byte out of the card
|
|||||||
movlb 0 ; return
|
movlb 0 ; return
|
||||||
return ; "
|
return ; "
|
||||||
|
|
||||||
;Stop a multiblock read or write, if one is ongoing, and deassert !CS. Sets
|
;Try to advance to the state requested in W, timing out if Timer1 overflows.
|
||||||
; M_FAIL on fail. Trashes X0 and X1.
|
; Trashes X0.
|
||||||
MmcStopOngoing
|
MmcWaitState
|
||||||
bcf M_FLAGS,M_FAIL ;Assume no failure to start with
|
movwf X0 ;Save the state caller wants to get to
|
||||||
btfsc M_FLAGS,M_MBWR ;If there's an ongoing write operation, make it
|
movlw B'00110001' ;Turn on Timer1
|
||||||
bra MmcSto0 ; stop
|
movwf T1CON ; "
|
||||||
btfss M_FLAGS,M_MBRD ;If there's not an ongoing read operation, this
|
bcf PIR1,TMR1IF ;Clear the Timer1 interrupt flag if it was set
|
||||||
return ; function was called needlessly, return
|
movf M_STATE,W ;If we're already in the state caller wants to
|
||||||
movlw 0x4C ;Send a CMD12 to stop the ongoing read, R1b
|
xorwf X0,W ; be in, skip ahead
|
||||||
movwf M_CMDN ; reply type
|
btfsc STATUS,Z ; "
|
||||||
clrf M_ADR3 ; "
|
bra MmcWaS1 ; "
|
||||||
clrf M_ADR2 ; "
|
MmcWaS0 call MmcStepState ;Step the state
|
||||||
clrf M_ADR1 ; "
|
movf M_STATE,W ;If we're now in the state caller wants to be
|
||||||
clrf M_ADR0 ; "
|
xorwf X0,W ; in, skip ahead
|
||||||
bcf M_FLAGS,M_CMDLR ; "
|
btfsc STATUS,Z ; "
|
||||||
bsf M_FLAGS,M_CMDRB ; "
|
bra MmcWaS1 ; "
|
||||||
call MmcCmd ; "
|
btfsc PIR1,TMR1IF ;If Timer1 overflowed, skip ahead
|
||||||
bcf M_FLAGS,M_MBRD ;Clear the ongoing multiblock read flag
|
bra MmcWaS2 ; "
|
||||||
bsf CS_PORT,CS_PIN ;Deassert !CS
|
bra MmcWaS0 ;Loop until something happens
|
||||||
return
|
MmcWaS1 bcf T1CON,TMR1ON ;Stop Timer1 and clear its interrupt flag so
|
||||||
MmcSto0 movlb 4 ;Switch to the bank with the SSP registers
|
bcf PIR1,TMR1IF ; caller knows we're in the state requested and
|
||||||
movlw 0xFD ;Clock the end-of-data token into the MMC card
|
return ; did not time out
|
||||||
|
MmcWaS2 bcf T1CON,TMR1ON ;Stop Timer1 and leave its interrupt flag set
|
||||||
|
return ; so caller knows a timeout occurred
|
||||||
|
|
||||||
|
;State machine to ensure that the card stays in a good state.
|
||||||
|
MmcStepState
|
||||||
|
btfss PIR1,SSP1IF ;If the SSP is busy, we can't do anything, so
|
||||||
|
return ; return
|
||||||
|
movlb 4 ;Switch depending on the current state
|
||||||
|
movf M_STATE,W ; "
|
||||||
|
call MSSCall ; "
|
||||||
|
movwf M_STATE ;Save the returned value in W as the new state
|
||||||
|
movlb 0 ; and return
|
||||||
|
movlp 8 ; "
|
||||||
|
return ; "
|
||||||
|
MSSCall brw
|
||||||
|
MSS
|
||||||
|
MSSWaitCmd
|
||||||
|
btfss M_FLAGS,M_RDCMD ;If we're not set to do a read command, cycle
|
||||||
|
retlw MSSWaitCmd - MSS; back to this state doing nothing
|
||||||
|
movlb 0 ;Assert !CS
|
||||||
|
bcf CS_PORT,CS_PIN ; "
|
||||||
|
movlb 4 ; "
|
||||||
|
movlw 0x51 ;Clock out the command byte for a read
|
||||||
movwf SSP1BUF ; "
|
movwf SSP1BUF ; "
|
||||||
btfss SSP1STAT,BF ; "
|
movlw 0xE8 ;Set up the CRC register with the CRC7 of the
|
||||||
bra $-1 ; "
|
movwf M_CRCL ; read command byte
|
||||||
movlw 0xFF ;Clock a dummy byte while keeping MOSI high
|
movlb 0 ;Clear the SSP interrupt flag because it's in
|
||||||
|
bcf PIR1,SSP1IF ; use now
|
||||||
|
retlw MSSRdCmd1 - MSS ;Transition to the next read command state
|
||||||
|
MSSRdCmd1
|
||||||
|
movf M_ADR3,W ;Clock out the high byte of the address
|
||||||
movwf SSP1BUF ; "
|
movwf SSP1BUF ; "
|
||||||
btfss SSP1STAT,BF ; "
|
movlp high LutCrc7 ;Update the CRC for the command
|
||||||
bra $-1 ; "
|
xorwf M_CRCL,W ; "
|
||||||
call MmcWaitBusy ;Wait for the card to not be busy anymore
|
callw ; "
|
||||||
movlb 0 ;Return to the default bank
|
movwf M_CRCL ; "
|
||||||
bcf M_FLAGS,M_MBWR ;Clear the ongoing multiblock write flag
|
movlb 0 ;Clear the SSP interrupt flag because it's in
|
||||||
bsf CS_PORT,CS_PIN ;Deassert !CS
|
bcf PIR1,SSP1IF ; use now
|
||||||
return
|
retlw MSSRdCmd2 - MSS ;Transition to the next read command state
|
||||||
|
MSSRdCmd2
|
||||||
|
movf M_ADR2,W ;Clock out the next byte of the address
|
||||||
|
movwf SSP1BUF ; "
|
||||||
|
movlp high LutCrc7 ;Update the CRC for the command
|
||||||
|
xorwf M_CRCL,W ; "
|
||||||
|
callw ; "
|
||||||
|
movwf M_CRCL ; "
|
||||||
|
movlb 0 ;Clear the SSP interrupt flag because it's in
|
||||||
|
bcf PIR1,SSP1IF ; use now
|
||||||
|
retlw MSSRdCmd3 - MSS ;Transition to the next read command state
|
||||||
|
MSSRdCmd3
|
||||||
|
movf M_ADR1,W ;Clock out the next byte of the address
|
||||||
|
movwf SSP1BUF ; "
|
||||||
|
movlp high LutCrc7 ;Update the CRC for the command
|
||||||
|
xorwf M_CRCL,W ; "
|
||||||
|
callw ; "
|
||||||
|
movwf M_CRCL ; "
|
||||||
|
movlb 0 ;Clear the SSP interrupt flag because it's in
|
||||||
|
bcf PIR1,SSP1IF ; use now
|
||||||
|
retlw MSSRdCmd4 - MSS ;Transition to the next read command state
|
||||||
|
MSSRdCmd4
|
||||||
|
movf M_ADR0,W ;Clock out the low byte of the address
|
||||||
|
movwf SSP1BUF ; "
|
||||||
|
movlp high LutCrc7 ;Update the CRC for the command
|
||||||
|
xorwf M_CRCL,W ; "
|
||||||
|
callw ; "
|
||||||
|
movwf M_CRCL ; "
|
||||||
|
movlb 0 ;Clear the SSP interrupt flag because it's in
|
||||||
|
bcf PIR1,SSP1IF ; use now
|
||||||
|
retlw MSSRdCmd5 - MSS ;Transition to the next read command state
|
||||||
|
MSSRdCmd5
|
||||||
|
movf M_CRCL,W ;Clock out the CRC for the command
|
||||||
|
movwf SSP1BUF ; "
|
||||||
|
bcf M_FLAGS,M_RDCMD ;Read command complete, M_ADR* are free
|
||||||
|
movlb 0 ;Clear the SSP interrupt flag because it's in
|
||||||
|
bcf PIR1,SSP1IF ; use now
|
||||||
|
retlw MSSRdCmd6 - MSS ;Transition to the next read command state
|
||||||
|
MSSRdCmd6
|
||||||
|
movlw 0xFF ;Clock first is-still-busy? byte out of the
|
||||||
|
movwf SSP1BUF ; card
|
||||||
|
movlb 0 ;Clear the SSP interrupt flag because it's in
|
||||||
|
bcf PIR1,SSP1IF ; use now
|
||||||
|
retlw MSSRdCmd7 - MSS ; "
|
||||||
|
MSSRdCmd7
|
||||||
|
btfss SSP1BUF,7 ;If MSB is set, this isn't an R1 response byte,
|
||||||
|
bra $+6 ; so clock out another byte and try again
|
||||||
|
movlw 0xFF ; "
|
||||||
|
movwf SSP1BUF ; "
|
||||||
|
movlb 0 ; "
|
||||||
|
bcf PIR1,SSP1IF ; "
|
||||||
|
retlw MSSRdCmd7 - MSS ; "
|
||||||
|
movf SSP1BUF,W ;If MSB is clear but an error bit is set, the
|
||||||
|
andlw B'11111110' ; command was not processed, so go back to the
|
||||||
|
btfsc STATUS,Z ; WaitCmd state after deasserting !CS
|
||||||
|
bra $+4 ; "
|
||||||
|
movlb 0 ; "
|
||||||
|
bsf CS_PORT,CS_PIN ; "
|
||||||
|
retlw MSSWaitCmd - MSS; "
|
||||||
|
movlw 0xFF ;If all error bits are clear in the response
|
||||||
|
movwf SSP1BUF ; byte, clock out the first is-read-token? byte
|
||||||
|
movlb 0 ; "
|
||||||
|
bcf PIR1,SSP1IF ; "
|
||||||
|
retlw MSSRdTok - MSS ; "
|
||||||
|
MSSRdTok
|
||||||
|
movf SSP1BUF,W ;Check if the byte read from the card is the
|
||||||
|
xorlw 0xFE ; read token
|
||||||
|
btfsc STATUS,Z ;If the byte read was not the read token, start
|
||||||
|
bra $+6 ; the next byte clocking out and remain in this
|
||||||
|
movlw 0xFF ; state for next call
|
||||||
|
movwf SSP1BUF ; "
|
||||||
|
movlb 0 ; "
|
||||||
|
bcf PIR1,SSP1IF ; "
|
||||||
|
retlw MSSRdTok - MSS ; "
|
||||||
|
movlw 0xFD ;If byte read was the read token, transition
|
||||||
|
movwf M_CRCH ; to RdData using CRC register as an up counter
|
||||||
|
movwf M_CRCL ; set to -515 (512 bytes + 2 CRC bytes + 1),
|
||||||
|
retlw MSSRdData - MSS ; assuming we have to throw away the read data
|
||||||
|
MSSRdData
|
||||||
|
incf M_CRCL,F ;Step the up counter
|
||||||
|
btfsc STATUS,Z ; "
|
||||||
|
incf M_CRCH,F ; "
|
||||||
|
btfss STATUS,Z ;If the up counter overflowed, deassert !CS
|
||||||
|
bra $+4 ; and reset the state to WaitCmd without
|
||||||
|
movlb 0 ; starting a byte clocking
|
||||||
|
bsf CS_PORT,CS_PIN ; "
|
||||||
|
retlw MSSWaitCmd - MSS; "
|
||||||
|
movlw 0xFF ;Start the next byte to read clocking out and
|
||||||
|
movwf SSP1BUF ; stay in this state for next time
|
||||||
|
movlb 0 ; "
|
||||||
|
bcf PIR1,SSP1IF ; "
|
||||||
|
retlw MSSRdData - MSS ; "
|
||||||
|
MSSWrEtTok
|
||||||
|
btfsc M_FLAGS,M_ONGWR ;If there's an ongoing write, don't proceed in
|
||||||
|
retlw MSSWrEtTok - MSS; sending an end tran token
|
||||||
|
movlw 0xFD ;Start an end tran token clocking
|
||||||
|
movwf SSP1BUF ; "
|
||||||
|
movlb 0 ;Clear the SSP interrupt flag because it's in
|
||||||
|
bcf PIR1,SSP1IF ; use now
|
||||||
|
retlw MSSEtJnk1 - MSS ;Transition to EtJnk1
|
||||||
|
MSSEtJnk1
|
||||||
|
movlw 0xFF ;Byte we got in when we clocked out the end
|
||||||
|
movwf SSP1BUF ; tran token is junk, so is the next one
|
||||||
|
movlb 0 ;Clear the SSP interrupt flag because it's in
|
||||||
|
bcf PIR1,SSP1IF ; use now
|
||||||
|
retlw MSSEtJnk2 - MSS ;Transition to EtJnk2
|
||||||
|
MSSEtJnk2
|
||||||
|
movlw 0xFF ;Byte we got in from previous state is junk,
|
||||||
|
movwf SSP1BUF ; the one we're clocking now is legit
|
||||||
|
movlb 0 ;Clear the SSP interrupt flag because it's in
|
||||||
|
bcf PIR1,SSP1IF ; use now
|
||||||
|
retlw MSSEtBusy - MSS ;Transition to EtBusy
|
||||||
|
MSSEtBusy
|
||||||
|
movf SSP1BUF,W ;If the byte we read out of the card is not all
|
||||||
|
btfsc STATUS,Z ; zeroes, deassert !CS and transition to
|
||||||
|
bra $+4 ; WaitCmd
|
||||||
|
movlb 0 ; "
|
||||||
|
bsf CS_PORT,CS_PIN ; "
|
||||||
|
retlw MSSWaitCmd - MSS; "
|
||||||
|
movlw 0xFF ;If the byte we read out of the card is all
|
||||||
|
movwf SSP1BUF ; zeroes, clock the next one out while keeping
|
||||||
|
movlb 0 ; MOSI high and stay in this state
|
||||||
|
bcf PIR1,SSP1IF ; "
|
||||||
|
retlw MSSEtBusy - MSS ; "
|
||||||
|
MSSWrBusy
|
||||||
|
movf SSP1BUF,W ;If the byte clocked in is 0x00, clock another
|
||||||
|
btfss STATUS,Z ; byte out and return to this state
|
||||||
|
bra $+6 ; "
|
||||||
|
movlw 0xFF ; "
|
||||||
|
movwf SSP1BUF ; "
|
||||||
|
movlb 0 ; "
|
||||||
|
bcf PIR1,SSP1IF ; "
|
||||||
|
retlw MSSWrBusy - MSS ; "
|
||||||
|
btfsc M_FLAGS,M_ONGWR ;If there's an ongoing write, transition to let
|
||||||
|
retlw MSSWrEtTok - MSS; the caller send a data token if it wants to
|
||||||
|
movlw 0xFD ;Else, start an end tran token clocking
|
||||||
|
movwf SSP1BUF ; "
|
||||||
|
movlb 0 ;Clear the SSP interrupt flag because it's in
|
||||||
|
bcf PIR1,SSP1IF ; use now
|
||||||
|
retlw MSSEtJnk1 - MSS ;Transition to EtJnk1
|
||||||
|
|
||||||
|
|
||||||
;;; End of Program ;;;
|
;;; End of Program ;;;
|
||||||
|
Loading…
Reference in New Issue
Block a user