.org   000h
ljmp   start

.org   003h
ljmp   isr

.org   080h
.db    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF    ; Buffer
.db    0x40, 0x00, 0x00, 0x00, 0x00, 0x95    ; CMD0
.db    0x77, 0x00, 0x00, 0x00, 0x00, 0x00    ; CMD55
.db    0x69, 0x00, 0x00, 0x00, 0x00, 0x00    ; ACMD41
.db    0x51, 0x00, 0x00, 0x00, 0x00, 0x00    ; CMD17     ; This command reads the first 16 bytes of the block at SD card address located at 0xR7, 0xR6, 0xR5, 0xR4 to the scratch-pad memory at 0x30

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;                                                                                              ;;;
;;;                                  Main Code Written Below                                     ;;;
;;;                                                                                              ;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

.org   300h
start:
	lcall init
main:
	mov   R0,  #30h
	mov   R1,  #10h
	mainLoop:
		mov   a,  @R0
		mov   P1, a
		
		mov    R2, #00h		   ; Wait a second or two
		mov    R3, #00h
		mov    R4, #02h
		delay:
			djnz   R2, delay
			djnz   R3, delay
			djnz   R4, delay
		
		inc   R0
		djnz  R1, mainLoop
	sjmp  main
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;                                                                                              ;;;
;;;                                  Main Code Written Above                                     ;;;
;;;                                                                                              ;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;                                                                                              ;;;
;;;                                Initialization Written Below                                  ;;;
;;;                                                                                              ;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

init:
; Set up serial communication to the computer
	mov   tmod, #20h       ; set timer 1 for auto reload - mode 2   
    mov   tcon, #41h       ; run counter 1 and set edge trig ints
    mov   th1,  #0fdh      ; set 9600 baud with xtal=11.059mhz
    mov   scon, #50h       ; set serial control reg for 8 bit data
                           ; and mode 1
						  
	mov   IE,   #81h       ; Fully enable the edge triggered interrupt
	
	mov   dptr, #0xFE03    ; Set the PSOC SPI to 200kBS communication and turn it on
	mov   a, #0x43
	movx  @dptr, a

	lcall SDinit
	
	mov   R7, #00h		   ; Read in the block starting at address 0x00000200h - Sector 1
	mov   R6, #00h		   ; This command is modified from the one in SD_Sector_Copier
	mov   R5, #02h		   ; This command is meant to work with no ram for the 8051.
	mov   R4, #00h		   ; It reads the first 16 bytes into scratch-pad memory starting at 0x30
	lcall CMD17mod		   ; And dumps the rest!
	
	ret
	
SDinit:
	mov   R1, #80h         ; Here we send 74+ clock pulses to ready the SD card
	lcall SDSend  
	mov   R1, #80h
	lcall SDSend
	
	lcall CMD0             ; Here we send CMD0 to put the SD card in IDLE mode for a software reset.
	
	lcall ACMD41		   ; Here we send ACMD41 to initialize the SD card and take it out of IDLE mode.
						   ; After this, the card is ready to use.
						   
	ret
	
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;                                                                                              ;;;
;;;                                Initialization Written Above                                  ;;;
;;;                                                                                              ;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;                                                                                              ;;;
;;;                                       ISR Written Below                                      ;;;
;;;                                                                                              ;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

isr:
	mov   dptr, #0xFE03    ; Clear the PSoC SPI flag thus clearing the external interrupt
	mov   a, #0x43
	movx  @dptr, a
		
	setb  00h
	reti                   ; Return

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;                                                                                              ;;;
;;;                                       ISR Written Above                                      ;;;
;;;                                                                                              ;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;                                                                                              ;;;
;;;                         SD Card Support Subroutines Written Below                            ;;;
;;;                                                                                              ;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

SDSendByte:										 ; This subroutine sends the value of a over the SPI port and waits till the shift is complete.
	mov   dptr,  #0xFE04
	movx  @dptr, a
	clr   00h
	Hold:
		jnb   00h, Hold
	ret
	
SDSend:                                          ; This subroutine sends 6 bytes of data to the SD card starting
	mov   R2, #0x06                              ; With the byte stored in 8051 memory location 0x00XX where XX is
	SDSendLoop:		                             ; Determined by the value in R1
		mov   dph,   #00h
		mov   dpl,   R1
		movx  a,     @dptr
		lcall SDSendByte
		inc   R1
		djnz  R2, SDSendLoop
	ret
	
SDSendScratch:                                   ; This subroutine sends 6 bytes of data to the SD card starting
	mov   R2, #0x06                              ; With the byte stored in 8051 scratch-pad memory location starting
	mov   R1, #0x40                              ; at 0x40
	SDSendLoopS:		                             
		mov   a,     @R1
		lcall SDSendByte
		inc   R1
		djnz  R2, SDSendLoopS
	ret
	
SDRead:                                          ; This subroutine searches for a response from the SD card following a SDSend command
	mov   R2, #0xFF                              ; It returns with either the first byte of the response or a failed response value of
	SDReadLoop:                                  ; 0xFF stored in R2
		mov   dptr,  #0xFE04
		mov   a, #0xFF
		lcall SDSendByte
		mov   dptr,  #0xFE04
		movx  a,     @dptr
		cjne  a, #0xFF, SDReadDone
		djnz  R2, SDReadLoop
		mov   R2, 0xFF
		ret
	
	SDReadDone:
		mov   R2, a
		ret
		
CMD0:                                            ; This subroutine sends the CMDO command to the SD card.  It makes use of SDSend and
	mov   R3, #0xFF                              ; SDRead to accomplish this.  If this command fails, the LED's on P1 will show 0x00.
	CMD0Loop:                                    ; If this command succeeds, the LED's will be left as 0xFF - as they were at start-up.
		mov   R1, #86h
		lcall SDSend  
		lcall SDRead
		cjne  R2, #01h, CMD0Error
		sjmp  CMD0Done
		CMD0Error:
			mov   R1, #80h
			lcall SDSend
			djnz  R3, CMD0Loop
			
			mov   P1, #00h
			lcall SDError
	CMD0Done:
		mov   R1, #80h
		lcall SDSend
		ret
			
ACMD41:                                          ; This subroutine sends the ACMD41 command to the SD card.  It makes use of SDSend and 
	mov   R3, #0xFF                              ; SDRead to accomplish this.  If this command fails, the LED's on P1 will show 0x41.
	ACMD41Loop:									 ; If this command succeeds, the LED's will be left as 0xFF - as they were at start-up.
		mov   R1, #8Ch
		lcall SDSend  
		lcall SDRead
		mov   R1, #80h
		lcall SDSend
		mov   R1, #92h
		lcall SDSend  
		lcall SDRead
		cjne  R2, #00h, ACMD41Error
		sjmp  ACMD41Done
		ACMD41Error:
			mov   R1, #80h
			lcall SDSend
			djnz  R3, ACMD41Loop
			
			mov   P1, #41h
			lcall SDError
	ACMD41Done:
		mov   R1, #80h
		lcall SDSend
		ret
		
CMD17mod:                                        ; This subroutine sends the CMD17 command to the SD card.  The address argument it uses is the values in
												 ; R7, R6, R5, R4.  It saves the read values to the buffer space 0x100 to 0x2FF within RAM.  It makes use of SDSend and
	mov   dptr,  #0x0098						 ; SDRead to accomplish this.  If this command fails, the LED's on P1 will show 0x17.
	mov   R0,    #40h                            ; If this command succeeds, the LED's will be left as 0xFF - as they were at start-up.
	movx  a,     @dptr
	mov   @R0,   a
	inc   R0
	
	mov   a,     R7								 
	mov   @R0, a
	inc   R0
	
	mov   a,     R6
	mov   @R0, a
	inc   R0
	
	mov   a,     R5
	mov   @R0, a
	inc   R0
	
	mov   a,     R4
	mov   @R0, a
	inc   R0
	
	mov   dptr,  #0x009D          
	movx  a,     @dptr
	mov   @R0,   a

	mov   R3, #0xFF                              
	CMD17Loop:                                   
		lcall SDSendScratch
		lcall SDRead
		cjne  R2, #00h, CMD17Error
		sjmp  CMD17Done
		CMD17Error:
			mov   R1, #80h
			lcall SDSend
			djnz  R3, CMD17Loop
			
			mov   P1, #17h
			lcall SDError
	CMD17Done:									 ; This part of CMD17 reads data in from the SD card.  If this fails, the P1 LED's will show 0xF0
		lcall SDRead
		cjne  R2, #0xFE, ReadError
		
		clr   01h
		mov   R4, #01h
		mov   R5, #00h
		
		mov   R7, #00h
		mov   R6, #02h
		ReadLoop:
			mov   dptr,  #0xFE04
			mov   a,     #0xFF
			lcall SDSendByte
			mov   dptr,  #0xFE04
			movx  a,     @dptr
			jb    01h,   modSkip
			mov   b,     a
			mov   a,     #30h
			add   a,     R5
			mov   R0,    a
			mov   a,     b
			mov   @R0,   a
			modSkip:
			inc   R5
			cjne  R5, #10h, modSkip2
			setb  01h
			modSkip2:
			cjne  R5, #00h, ReadContinue
			inc   R4
			ReadContinue:
				djnz  R7, ReadLoop
				djnz  R6, ReadLoop
			ret
		ReadError:
			mov   P1, #0xF0
			ljmp  SDError

SDError:
	sjmp  SDError

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;                                                                                              ;;;
;;;                         SD Card Support Subroutines Written Above                            ;;;
;;;                                                                                              ;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	