title "CompactFlash" ; ; ; ; LIST P=16F877, R=DEC ; errorlevel 0,-305,-302***** ;****************************************************************************** ;** ** ;** COMPACTFLASH CARD TO PIC INTERFACE ** ;** ** ;** MARK A. SAMUELS ** ;** ** ;****************************************************************************** INCLUDE "e:\mp3playerJunk\mplab\P16F877.inc" ;************************************************************************* ;****************************************************************************** ; Registers __CONFIG _CP_OFF & _WDT_OFF & _XT_OSC & _PWRTE_ON & _LVP_OFF ; VARIABLE DECLARATIONS ;****************************************************************************** TEMP_W EQU 0x20 TEMP_S EQU 0x21 REGA EQU TEMP_S + 1 REGB EQU REGA + 1 REGC EQU REGB + 1 REGD EQU REGC + 1 REGE EQU REGD + 1 DATA_HI EQU REGE + 1 DATA_LO EQU DATA_HI + 1 COUNTER_LO EQU DATA_LO + 1 COUNTER_HI EQU COUNTER_LO + 1 SECTORS_LO EQU COUNTER_HI + 1 SECTORS_HI EQU SECTORS_LO + 1 BUFSIZE_LO EQU SECTORS_HI + 1 BUFSIZE_HI EQU BUFSIZE_LO + 1 regx EQU BUFSIZE_HI + 1 regy EQU regx + 1 regz EQU regy + 1 regt EQU regz + 1 regu EQU regt + 1 regv EQU regu + 1 rollerlo equ regv + 1 rollerhi equ rollerlo + 1 regnosub equ rollerhi + 1 bassboostbuffer equ regnosub + 1 volumebuffer equ bassboostbuffer + 1 bassslower equ volumebuffer + 1 ; PORT DECLARATIONS ;****************************************************************************** CF_DATA EQU PORTD CF_ADDR EQU PORTE CF_CONTROL EQU PORTA userport equ portb ; FLAG DECLARATIONS ;****************************************************************************** ; CF CONTROL CE1 EQU 0 ; CF CONTROL PORT, 0 (LOW = ENABLE, HI = HI-Z) CD1 EQU 1 ; CF CONTROL PORT, 1 RESET EQU 2 ; CF CONTROL PORT, 2 OE EQU 3 ; CF CONTROL PORT, 3 WE EQU 4 ; CF CONTROL PORT, 4 RDY EQU 5 ; CF CONTROL PORT, 5 ;these are port c, mostly vscontrol equ portc bsync equ 0 dreq equ 1 dclk equ 6 sdata equ 7 xcs equ 2 sclk equ 3 si equ 5 so equ 4 xreset equ 2 ;this is on port b!!!! userreset equ 3 bassboost equ 4 volume equ 5 skipbutton equ 6 surround equ 7 ; CF CARD REGISTER ADDRESSES ;****************************************************************************** ; ADDRESS VALUES, LOW 3 BITS AS FOLLOWS: ; (X,X,X,X,X,A2,A1,A0) DATA_REG EQU 0x00 ; ADDRESS OF DATA REGISTER ERROR_REG EQU 0x01 ; ADDRESS OF ERROR REGISTER FEATURES_REG EQU 0x01 ; ADDRESS OF FEATURES REGISTER SEC_CNT_REG EQU 0x02 ; ADDRESS OF SECTOR COUNT REGISTER SEC_NUM_REG EQU 0x03 ; ADDRESS OF SECTOR NUMBER REGISTER CYL_LO_REG EQU 0x04 ; ADDRESS OF LOW CYLINDER REGISTER CYL_HI_REG EQU 0x05 ; ADDRESS OF HIGH CYLINDER REGISTER HEAD_REG EQU 0x06 ; ADDRESS OF HEAD/DRIVE REGISTER STATUS_REG EQU 0x07 ; ADDRESS OF STATUS REGISTER COMMAND_REG EQU 0x07 ; ADDRESS OF COMMAND REGISTER ; COMMAND ASSIGNMENTS ;****************************************************************************** ; COMMAND VALUES, 8 BITS IDENTIFY EQU 0xEC WRITE_SEC EQU 0x30 READ_SEC EQU 0x20 PAGE org 0 NOP goto PRE_MAIN org 4 goto Int ;****************************************************************************** ;****************************************************************************** ;** ** ;** INTERRUPT SERVICE ROUTINE ** ;** ** ;****************************************************************************** ;****************************************************************************** ; (NO INTERRUPTS IN THIS CODE... ONLY HEADER AND FOOTER FOR ISR) Int movwf TEMP_W swapf STATUS, w movwf TEMP_S ; check int source here goto End_of_Int End_of_Int swapf TEMP_S, w movwf STATUS swapf TEMP_W, f swapf TEMP_W, w retfie ;++++++++++++++++++++++++++++++++++++++++subroutines ;****************************************************************************** ;* CHECK_READY SUBROUTINE * ;****************************************************************************** CHECK_READY BTFSS CF_CONTROL,RDY ; CHECK IF CF READY GOTO CHECK_READY RETURN ;****************************************************************************** ;* CF WRITE SUBROUTINE * ;****************************************************************************** CF_WRITE ; ENSURE CARD IS READY CALL CHECK_READY NOP ; STROBE "WE" LINE LOW BCF CF_CONTROL, WE NOP NOP NOP BSF CF_CONTROL, WE NOP RETURN ;****************************************************************************** ;* CF READ SUBROUTINE * ;****************************************************************************** CF_READ ; READ TWO BYTES CALL CHECK_READY ; SET TRIS REGISTERS FOR DATA LINES TO INPUT BSF STATUS, RP0 MOVLW 0xFF MOVWF CF_DATA BCF STATUS, RP0 NOP CLRF CF_DATA ; SET OE LINE LOW NOP BCF CF_CONTROL, OE NOP NOP NOP ; READ AND STORE BYTE #1 MOVF CF_DATA,W MOVWF DATA_LO NOP ; SET OE LINE HI BSF CF_CONTROL, OE NOP NOP CALL CHECK_READY ; BYTE #2 ; SET OE LINE LOW NOP BCF CF_CONTROL, OE NOP NOP NOP ;READ AND STORE BYTE #2 MOVF CF_DATA,W MOVWF DATA_HI NOP ; SET OE LINE HI BSF CF_CONTROL, OE NOP ; CHANGE CF_DATA BACK TO OUTPUT BSF STATUS, RP0 CLRF CF_DATA BCF STATUS, RP0 NOP RETURN ;************************************************************************ ;* ONE_SEC * ;* GENERATES ONE SECOND DELAY * ;************************************************************************ ONE_SEC MOVLW .255 MOVWF REGD GOTO ONE100 HALF_SEC MOVLW .128 MOVWF REGD ONE100 CALL DELAY DECFSZ REGD,F GOTO ONE100 RETURN ;****************************************************************************** ;* DELAY SUBROUTINE * ;****************************************************************************** DELAY MOVLW .2 ; # OF 1MS DELAYS MOVWF REGB DL100 CLRF REGC DL200 ;------\ NOP ; \ ; \ DECFSZ REGC,F ; > 1 MS (APPROX) GOTO DL200 ; / ; / DECFSZ REGB,F ;------/ GOTO DL100 ; RETURN ;------------------------------------------------------------------------------ serial_delay MOVLW .52 MOVWF REGy Serial_byte_delay DECFSZ REGy,F GOTO Serial_byte_delay RETURN nop ;--------------------------------------------------------------------------- CFread_VSsend ; READ TWO BYTES CALL CHECK_READY BSF STATUS, RP0 ; SET TRIS REGISTERS FOR DATA LINES TO INPUT MOVLW 0xFF MOVWF CF_DATA BCF STATUS, RP0 CLRF CF_DATA ;is this needed BCF CF_CONTROL, OE ; SET OE LINE LOW MOVF CF_DATA,W ; READ AND STORE BYTE #1 BSF CF_CONTROL, OE ; SET OE LINE HI ;bsf portb,4;------------- ;nop;------------------------ ;nop;--------------------- ;bcf portb,4;------------- ; movlw 0xf5 bsf vscontrol,bsync movwf txreg nop nop bcf vscontrol,bsync CALL CHECK_READY BCF CF_CONTROL, OE ; BYTE #2 ; SET OE LINE LOW MOVF CF_DATA,W ;READ AND STORE BYTE #2 BSF CF_CONTROL, OE ; SET OE LINE HI bsf vscontrol,bsync movwf txreg nop nop bcf vscontrol,bsync BSF STATUS, RP0 ; CHANGE CF_DATA BACK TO OUTPUT CLRF CF_DATA BCF STATUS, RP0 RETURN spiout movwf sspbuf nop nop nop nop nop nop nop nop nop nop return ;++++++++++++++++++++++++++++++++++++++++ sdi_out bsf vscontrol,bsync movwf txreg nop nop bcf vscontrol,bsync nop nop nop nop return ;+++++++++++++++++++++++++++++++++++++++++++ resetvs1001 ;reset and mode set bcf vscontrol,xcs movlw 0x02 call spiout movlw 0x00 call spiout movlw 0x03 call spiout movlw 0x04 call spiout bsf vscontrol,xcs call delay ;unreset and mode set bcf vscontrol,xcs movlw 0x02 call spiout movlw 0x00 call spiout movlw 0x03 call spiout movlw 0x00 call spiout bsf vscontrol,xcs call delay morezeroes check_vs_a BTFSS vscontrol,dreq ; CHECK IF vs1001 READY GOTO CHECK_vs_a movlw 0x00 call sdi_out call sdi_out call sdi_out call sdi_out decfsz regnosub goto morezeroes return ;+++++++++++++++++subroutines end ;***************************************************************************** ;***************************************************************************** PRE_MAIN ;***************************************************************************** ;***************************************************************************** ; CLEAR MEMORY SPACE (SET ALL RAM VALUES TO 0x00) GOTO INIT_DONE INIT_DONE ; Setup BSF STATUS, RP0 ; Goto Bank 1 MOVLW 0x00 MOVWF TRISA ; Set RC(7:0) as outputs MOVWF TRISD ; Set RD(7:0) as outputs MOVWF TRISE ; Set RE(2:0) as outputs MOVLW 0xd2 ;1101 0010b MOVWF TRISC ; MOVLW 0xfb ;iiii ioii MOVWF TRISB ; bit 2 must be output for vs reset pin BSF CF_CONTROL,CD1 ; MAKE CD1 AN INPUT (CARD DETECT) BSF CF_CONTROL,RDY ; MAKE RDY AN INPUT (RDY/BSY) MOVLW 0x06 ; Set PORTA as digital I/O MOVWF ADCON1 MOVLW 0x00 ; MOVWF OPTION_REG BCF STATUS, RP0 ; Go back to Bank 0 MOVLW 0x00 MOVWF ADCON0 ;********************************************************************** ;********************************************************************** MAIN ;********************************************************************** ;********************************************************************** bcf portb,4 bsf vscontrol,xcs ;chip select off sci (active low) bcf portb,xreset ;reset vs1001 MOVLW 0x18 MOVWF CF_CONTROL MOVLW 0x00 MOVWF CF_ADDR bsf portb,xreset ;activate vs1001 ;ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo ;usart_setup ;synchronous, max speed bsf rcsta,spen bsf status,rp0 movlw .0 movwf spbrg ;bsf txsta,brgh bsf txsta,sync bcf txsta,tx9 bsf txsta,csrc bsf txsta,txen bcf status,rp0 call One_sec ;spi setup bsf status,rp0 bsf sspstat,cke bcf status,rp0 bsf sspcon,sspen ;enable port ;initialize vs1001 ;set volume bcf vscontrol,xcs movlw 0x02 call spiout movlw 0x0b call spiout movlw 0x25 call spiout movlw 0x25 call spiout movwf volumebuffer bsf vscontrol,xcs call delay ;ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo CHK_CARD BTFSC CF_CONTROL, CD1 ; CARD INSERTED? GOTO CHK_CARD ; NO, GO BACK ; YES, GO ON BSF CF_CONTROL, RESET ; RESET CF CARD NOP NOP BCF CF_CONTROL, RESET NOP NOP CALL HALF_SEC ; WRITE CF EXECUTE IDENTIFY DRIVE COMMAND (0xEC) MOVLW COMMAND_REG ; REGISTER TO BE ADRESSED MOVWF CF_ADDR MOVLW IDENTIFY ; INSTRUCTION CODE MOVWF CF_DATA CALL CF_WRITE ; READ DATA REGISTER MOVLW READ_SEC MOVWF CF_ADDR MOVLW .5 ; DROP FIRST 5 WORDS MOVWF REGA TRUNC1 CALL CF_READ DECFSZ REGA,F GOTO TRUNC1 ; READ AND STORE THE NUMBER OF BYTES PER SECTOR CALL CF_READ MOVLW .15 ; SKIP NEXT 15 WORDS MOVWF REGA TRUNC2 CALL CF_READ DECFSZ REGA,F GOTO TRUNC2 ; READ AND STORE THE BUFFER SIZE CALL CF_READ MOVF DATA_HI, W MOVWF BUFSIZE_HI MOVF DATA_LO, W MOVWF BUFSIZE_LO MOVLW 0x00 MOVWF regv MOVLW 0x02 MOVWF regu MOVLW 0x2B MOVWF regt call resetvs1001 ;+__+_+_++_+__+_+_+_+_++_ ;+_+_++__+_+_++_+____+_+ superread btfsc userport,userreset goto skipuserreset call resetvs1001 skipuserreset btfsc userport,volume goto skipvolume decf volumebuffer,f bcf vscontrol,xcs movlw 0x02 call spiout movlw 0x0b call spiout movf volumebuffer,w call spiout movf volumebuffer,w call spiout bsf vscontrol,xcs skipvolume btfsc userport,bassboost goto skipbassboost bcf vscontrol,xcs movlw 0x02 call spiout movlw 0x00 call spiout movlw 0x03 call spiout movlw 0x80 call spiout bsf vscontrol,xcs skipbassboost btfsc userport,surround goto skipsurround bcf vscontrol,xcs movlw 0x02 call spiout movlw 0x00 call spiout movlw 0x03 call spiout movlw 0x01 call spiout bsf vscontrol,xcs skipsurround btfsc userport,skipbutton goto notrackskip movlw 0x04 addwf regt,F BTFSC STATUS,Z INCF regu,F BTFSC STATUS,Z INCF regv,F notrackskip MOVLW 0xE0 MOVWF CF_DATA MOVLW HEAD_REG MOVWF CF_ADDR CALL CF_WRITE movf regv ,w MOVWF CF_DATA MOVLW CYL_HI_REG MOVWF CF_ADDR CALL CF_WRITE movf regu ,w MOVWF CF_DATA MOVLW CYL_LO_REG MOVWF CF_ADDR CALL CF_WRITE movf regt ,w MOVWF CF_DATA MOVLW SEC_NUM_REG MOVWF CF_ADDR CALL CF_WRITE MOVLW 0x01 MOVWF CF_DATA MOVLW SEC_CNT_REG MOVWF CF_ADDR CALL CF_WRITE MOVLW READ_SEC MOVWF CF_DATA MOVLW COMMAND_REG MOVWF CF_ADDR CALL CF_WRITE MOVLW DATA_REG MOVWF CF_ADDR movlw .16 movwf regx printout CHECK_vs BTFSS vscontrol,dreq ; CHECK IF vs1001 READY GOTO CHECK_vs CALL CFREAD_vssend CALL CFREAD_vssend CALL CFREAD_vssend CALL CFREAD_vssend CALL CFREAD_vssend CALL CFREAD_vssend CALL CFREAD_vssend CALL CFREAD_vssend CALL CFREAD_vssend CALL CFREAD_vssend CALL CFREAD_vssend CALL CFREAD_vssend CALL CFREAD_vssend CALL CFREAD_vssend CALL CFREAD_vssend CALL CFREAD_vssend DECFSZ REGX, F GOTO printout ; INCREMENT COUNTER INCF regt,F BTFSC STATUS,Z INCF regu,F BTFSC STATUS,Z INCF regv,F BTFSC STATUS,Z goto end_chk GOTO superread ; LOOP FOREVER UNTIL CARD REMOVED, THEN RESET END_CHK BTFSC CF_CONTROL,CD1 GOTO CHK_CARD GOTO END_CHK ; END OF MAIN LOOP retlw 'a' retlw 'z' retlw 'z' retlw 'h' retlw 'o' end