⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fat32.s

📁 Frank s MP3 Player Source Files
💻 S
📖 第 1 页 / 共 5 页
字号:
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 + -