📄 fat32.s
字号:
StreamFile_LC_J: jmp StreamFile_LC
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Idle state
StreamFile_IDL:
; If Command == Stop then return
ldi ZL,lo8(STREAMFILE_CMD)
ldi ZH,hi8(STREAMFILE_CMD) ; Z points to command variable
ld temp,Z
cpi temp,StreamFile_Cmd_Stop
brne StreamFile_IDL_1 ; branch forward if command NOT stop
ret ; Command == stop so return
; execute here if command is not Stop
; If filesize == 0 then write Stop into command variable & return
StreamFile_IDL_1:
ldi YL,lo8(STREAMFILE_FILESZ)
ldi YH,hi8(STREAMFILE_FILESZ) ; Y points to filesize (32 bits)
ldi temp,0
ld temp2,Y+
cp temp,temp2
brne StreamFile_IDL_2 ; branch if low FileSize byte not zero
ld temp2,Y+
cp temp,temp2
brne StreamFile_IDL_2 ; branch if next FileSize byte not zero
ld temp2,Y+
cp temp,temp2
brne StreamFile_IDL_2 ; branch if next FileSize byte not zero
ld temp2,Y
cp temp,temp2
brne StreamFile_IDL_2 ; branch if high FileSize byte not zero
ldi temp,StreamFile_Cmd_Stop ; FileSize == 0, so
st Z,temp ; write Stop into command variable
ret ; and return
; execute here if filesize != 0
; Change state variable to SeekCluster state and jump to SeekCluster state
StreamFile_IDL_2:
ldi ZL,lo8(STREAMFILE_ST)
ldi ZH,hi8(STREAMFILE_ST) ; point Z to StreamFile state variable
ldi temp,StreamFile_St_SeekClus
st Z,temp ; store state varible as SeekCluster
rjmp StreamFile_SC ; jump to SeekCluster state
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; SeekCluster state
; This is basically part of the SeekCluster2 state below. It just makes sure that the
; SeekSector routine is idle before the SeekCluster2 state tries to use it.
StreamFile_SC:
lds temp,SEEKSECT_ST
cpi temp,SeekSect_ISS ; is SeekSector idle?
breq StreamFile_SCAA ; yes - branch forward
; print debug message if SeekSector not idle, because it certainly should be
ldi param1,'S'
call UART_TxCharWait
ldi param1,'F'
call UART_TxCharWait
ldi param1,'-'
call UART_TxCharWait
ldi param1,'S'
call UART_TxCharWait
ldi param1,'C'
call UART_TxCharWait
ldi param1,'1'
call UART_TxCharWait
ldi param1,'\n'
call UART_TxCharWait
ldi param1,'\r'
call UART_TxCharWait
; end debug code
ldi temp,SeekSect_ISS
sts SEEKSECT_ST,temp ; force SeekSector into idle state
ret ; and return to check again next time
; execute here if SeekSector is idle
StreamFile_SCAA:
ldi temp,StreamFile_St_SeekClus2
sts STREAMFILE_ST,temp ; next state is SeekCluster2
; if Command == put cluster number (STREAMFILE_CLUS) in Q, low byte first
lds temp,STREAMFILE_CMD
cpi temp,StreamFile_Cmd_SmWithCl ; is command "StreamFile_Cmd_SmWithCl"?
brne StreamFile_SCAB ; branch forward if command NOT "stream with cluster numbers"
; execute here if command is "stream with cluster numbers" - put cluster number into data Q
lds ZL,STREAMFILE_QPOINTER
lds ZH,STREAMFILE_QPOINTER+1 ; load address of the data queue into Z
lds param1,STREAMFILE_CLUS
call Q_write ; low byte of cluster number in data Q
lds param1,STREAMFILE_CLUS+1
call Q_write
lds param1,STREAMFILE_CLUS+2
call Q_write
lds param1,STREAMFILE_CLUS+3 ; high byte of cluster number in data Q
call Q_write
StreamFile_SCAB:
rjmp StreamFile_SC2 ; might as well goto next state now
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; SeekCluster2 state
StreamFile_SC2:
; Store 512 in STREAMFILE_SEC_REM (16 bits) and store SEC_PER_CLUS in STREAMFILE_SECCLUS_REM (8 bits)
ldi ZL,lo8(STREAMFILE_SEC_REM)
ldi ZH,hi8(STREAMFILE_SEC_REM) ; Z points to STREAMFILE_SEC_REM
ldi temp,lo8(512)
st Z+,temp ; store low byte of 512
ldi temp,hi8(512)
st Z,temp ; store high byte of 512 into STREAMFILE_SEC_REM
ldi ZL,lo8(SEC_PER_CLUS)
ldi ZH,hi8(SEC_PER_CLUS)
ld temp,Z ; temp contains SEC_PER_CLUS
ldi ZL,lo8(STREAMFILE_SECCLUS_REM)
ldi ZH,hi8(STREAMFILE_SECCLUS_REM)
st Z,temp ; SEC_PER_CLUS copied to STREAMFILE_SECCLUS_REM
; Read cluster number from STREAMFILE_CLUS (32 bit), convert to a sector number & push onto stack
; To do this conversion we call the Cluster2Sector routine. Stack parameters are
; pushed high-byte first.
ldi ZL,lo8(STREAMFILE_CLUS)
ldi ZH,hi8(STREAMFILE_CLUS) ; Z points to STREAMFILE_CLUS low byte
ldd temp,Z+3 ; get high byte of cluster number
push temp ; and push it onto stack
ldd temp,Z+2
push temp
ldd temp,Z+1
push temp
ld temp,Z ; get low byte of cluster number
push temp ; and push it onto stack
rcall Cluster2Sector ; Convert to sector - result is on stack
; Get number of sectors per cluster (SEC_PER_CLUS) into param1 and call SeekSector
ldi ZL,lo8(SEC_PER_CLUS)
ldi ZH,hi8(SEC_PER_CLUS)
ld param1,Z ; number sectors per cluster in param1
rcall SeekSector ; result code in param1
pop temp
pop temp
pop temp
pop temp ; clean up the stack
; If SeekSector does not return "done" then Return
cpi param1,SeekSect_Done
breq StreamFile_SC_1 ; branch if SeekSector says "done"
ret ; return if SeekSector not done
; execute here if SeekSector says it's done
; Change state variable to ReadData state and jump to ReadData state
StreamFile_SC_1:
ldi ZL,lo8(STREAMFILE_ST)
ldi ZH,hi8(STREAMFILE_ST) ; point Z to StreamFile state variable
ldi temp,StreamFile_St_ReadData
st Z,temp ; store state varible as ReadData
rjmp StreamFile_RD ; jump to ReadData state
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ReadData state
StreamFile_RD:
; If Command == Stop then change state variable to idle state and return.
ldi ZL,lo8(STREAMFILE_CMD)
ldi ZH,hi8(STREAMFILE_CMD) ; Z points to command variable
ld temp,Z
cpi temp,StreamFile_Cmd_Stop
brne StreamFile_RD_1 ; branch forward if command NOT stop
ldi ZL,lo8(STREAMFILE_ST)
ldi ZH,hi8(STREAMFILE_ST) ; point Z to StreamFile state variable
ldi temp,StreamFile_St_Idle
st Z,temp ; store Idle state
ret ; and return
; execute here if there is no Stop command
; Determine the lowest of:
; Bytes remaining in the file (32 bits) (odd or even)
; Free bytes remaining in the MP3 data queue (16 bits) (even only)
; Bytes remaining in the current sector (16 bits) (even only)
; Number of bytes read permitted per execution (8 bits) (even only)
; We can cheat big-time here. Instead of converting all of these numbers to 32-bit values
; and doing a zillion comparisons, we can take advantage of the fact that the highest
; possible value of "bytes read per execution" is only 254. So we will convert each
; of the 32-bit & 16-bit numbers to an 8-bit value by simply saying: If any of the
; high bytes are non-zero then that number is automatically out of the running for being the lowest,
; otherwise the number will be the value of its low byte. R20 is used to keep the lowest
; value found.
StreamFile_RD_1:
ldi r20,StreamFile_MaxBytes ; # bytes read permissable per execution
ldi ZL,lo8(STREAMFILE_FILESZ)
ldi ZH,hi8(STREAMFILE_FILESZ) ; Z points to filesize (32 bits)
ldd temp,Z+3
cpi temp,0 ; is the high byte non-zero?
brne StreamFile_RD_2 ; branch if high byte not zero
ldd temp,Z+2
cpi temp,0 ; is the next byte non-zero?
brne StreamFile_RD_2 ; branch if byte not zero
ldd temp,Z+1
cpi temp,0 ; is the 3rd byte non-zero?
brne StreamFile_RD_2 ; branch if byte not zero
ld temp,Z ; filesize is value of low byte
cp temp,r20 ; is R20 less than filesize?
brsh StreamFile_RD_2 ; branch if temp >= R20
mov r20,temp ; else temp is the new lowvalue into r20
StreamFile_RD_2:
lds ZL,STREAMFILE_QPOINTER
lds ZH,STREAMFILE_QPOINTER+1 ; load address of the data queue into Z
rcall Q_query ; determine how much free space is in it
cpi param1,0
brne StreamFile_RD_3 ; branch forward if high byte not zero
andi param2,0xFE ; clear low bit of low byte (make it even)
cp param2,r20 ; is r20 less than Q free space?
brsh StreamFile_RD_3 ; branch if param2 >= R20
mov r20,param2 ; else param2 is new lowvalue into R20
StreamFile_RD_3:
ldi ZL,lo8(STREAMFILE_SEC_REM)
ldi ZH,hi8(STREAMFILE_SEC_REM)
ldd temp,Z+1 ; high byte of # bytes remaining in sector
cpi temp,0 ; is the high byte non-zero?
brne StreamFile_RD_4 ; branch if high byte != 0
ld temp,Z ; else temp = low byte of # bytes remaining
cp temp,r20 ; is r20 less than #bytes left in sector?
brsh StreamFile_RD_4 ; branch if temp >= R20
mov r20,temp ; else temp is new lowvalue into R20
StreamFile_RD_4:
; At this point r20 contains the lowest of the 4 numbers tested. Note that the ONLY way
; this number can be odd is if we're almost at the end of the file, and the number
; of bytes remaining in the file is odd. Otherwise this will be an even number.
; Call this result NumBytes (8 bit number) - keep a copy (NumberBytesRead)
; If NumBytes == 0 then return
mov r21,r20 ; copy of the result in r21 for later use
cpi r20,0
brne StreamFile_RD_5 ; branch forward if NumBytes != 0
ret ; return if NumBytes == 0
StreamFile_RD_5:
; Now we do this loop:
; Read 2 bytes from drive
; Place first byte in MP3 data queue
; Decrement NumBytes
; If NumBytes == 0 then exit this loop
; Place second byte in MP3 data queue
; Decrement NumBytes
; If NumBytes != 0 then loop back to read from drive again
lds ZL,STREAMFILE_QPOINTER
lds ZH,STREAMFILE_QPOINTER+1 ; load address of the data queue into Z
StreamFile_RD_6:
ldi param1,IDERD_DATA ; read 16-bit data from drive
call IDE_read16 ; first data byte is in param1
rcall Q_write ; write low byte into queue
dec r20 ; decrement NumBytes
breq StreamFile_RD_7 ; branch out if NumBytes == 0
mov param1,param2 ; copy second drive data byte into param1
rcall Q_write ; and place it in the queue
dec r20
brne StreamFile_RD_6 ; loop back if more bytes need to be read
StreamFile_RD_7:
; Filesize (STREAMFILE_FILESZ) = Filesize - NumberBytesRead (in r21)
ldi ZL,lo8(STREAMFILE_FILESZ)
ldi ZH,hi8(STREAMFILE_FILESZ) ; Z points to filesize (32 bits)
ld temp,Z ; temp contains low byte of filesize
sub temp,r21 ; subract NumBytesRead from lowbyte
st Z,temp ; store low byte back
ldi temp2,0
ldd temp,Z+1 ; temp contains next byte of filesize
sbc temp,temp2 ; subtract the carry flag from it
std Z+1,temp ; and store the result back
ldd temp,Z+2
sbc temp,temp2 ; subtract carry flag from 3rd byte
std Z+2,temp ; and store it back
ldd temp,Z+3
sbc temp,temp2 ; subtract carry flag from high byte
std Z+3,temp ; and store result back
; If FileSize == 0 then
; Write "stop" into command variable
; Change state variable to Idle state & return
ld temp,Z ; get low byte of filesize
cpi temp,0
brne StreamFile_RD_8 ; branch if filesize != 0
ldd temp,Z+1
cpi temp,0
brne StreamFile_RD_8 ; branch if filesize != 0
ldd temp,Z+2
cpi temp,0
brne StreamFile_RD_8 ; branch if filesize != 0
ldd temp,Z+3
cpi temp,0
brne StreamFile_RD_8 ; branch if filesize != 0
; execute here if filesize == 0
ldi ZL,lo8(STREAMFILE_CMD)
ldi ZH,hi8(STREAMFILE_CMD) ; Z points to command variable
ldi temp,StreamFile_Cmd_Stop
st Z,temp ; write Stop into command variable
ldi ZL,lo8(STREAMFILE_ST)
ldi ZH,hi8(STREAMFILE_ST) ; point Z to StreamFile state variable
ldi temp,StreamFile_St_Idle
st Z,temp ; store Idle state
ret ; and return
StreamFile_RD_8:
; BytesRemainingInSector (STREAMFILE_SEC_REM) = BytesRemainingInSector - NumberBytesRead
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -