;------------------------------------------------------------------------------- ; FILE: SD Card Part 2 ; AUTH: Ed's Projects ; DATE: 17/09/2017 ; DESC: Invalid entries from SD card are deleted from root directory. ; ; PortD LCD data bus ; PortC, 3 enable, 2 RW, 1 RS ; PortB 7-4 keypad rows, 3-0 keypad columns ;------------------------------------------------------------------------------- LIST P=18F4520, R=DEC ; All numbers Decimal format unless otherwise stated. include ; Define configurations, registers, etc. CONFIG OSC = INTIO67 ; 8 MHz internal oscillator CONFIG FCMEN = OFF ; Failsafe clock monitor off CONFIG IESO = OFF ; Internal / External oscillator switchover off CONFIG PWRT = ON ; Power up timer on CONFIG BOREN = OFF ; Brown out reset off CONFIG WDT = OFF ; Watchdog timer off CONFIG MCLRE = OFF ; Master reset pin off CONFIG LPT1OSC = OFF ; Low power timer 1 off CONFIG PBADEN = OFF ; PortB 4 to 0 digital on reset CONFIG LVP = OFF ; Low voltage programming off CONFIG XINST = OFF ; Extended instruction set enabled ;------------------------------------------------------------------------------- ;-------------------------------- Variables ---------------------------------- ;------------------------------------------------------------------------------- cblock 0x000 b0_temp b0_temp2 b0_temp3 temp1 temp2 temp3 temp4 temp5 ;memory counter temp6 ;memory counter temp7 ;SD card write counter temp8 ;SD card write counter MEMtemp ;memory chip temp E_adr E_data tmpctr offset digit1 ;BCD conversion digit2 ;BCD conversion digit3 ;BCD conversion digit4 ;BCD conversion digit5 ;BCD conversion digit6 ;BCD conversion digit7 ;BCD conversion digit8 ;BCD conversion digit9 ;BCD conversion digit10 ;BCD conversion count0 ;BCD conversion count1 ;BCD conversion count2 ;BCD conversion count3 ;BCD conversion bcdtmp1 ;BCD conversion bcdtmp2 ;BCD conversion arg1L ; Multiply arg1H ; Multiply arg2L ; Multiply arg2H ; Multiply result0 ; Multiply result1 ; Multiply result2 ; Multiply result3 ; Multiply R0 ; Divide R1 ; Divide R2 ; Divide Word0 ; Divide Word1 ; Divide Word2 ; Divide Word3 ; Divide DenL ; Divide DenH ; Divide lptmp Adr3 Adr2 Adr1 temp Adr8 ; SD card - Address read / write Adr16 ; SD card - Address read / write Adr24 ; SD card - Address read / write Adr32 ; SD card - Address read / write spbitL ; SD card spbitH ; SD card SPRtemp ; SD card SPItemp ; SD card sdadrser8 ; SD card - address offset sdadrser16 ; SD card - address offset sdadrser24 ; SD card - address offset sdadrser32 ; SD card - address offset bytesect8 ; SD card - bytes per sector bytesect16 ; SD card - bytes per sector sectclus ; SD card - sectors per cluster ressect8 ; SD card - reserved sectors ressect16 ; SD card - reserved sectors numFAT ; SD card - number of FAT's sectFAT8 ; SD card - Sectors per FAT sectFAT16 ; SD card - Sectors per FAT sectFAT24 ; SD card - Sectors per FAT sectFAT32 ; SD card - Sectors per FAT Ent0 ; SD card - File entry Ent1 ; SD card - File entry Ent2 ; SD card - File entry Ent3 ; SD card - File entry Ent4 ; SD card - File entry Ent5 ; SD card - File entry Ent6 ; SD card - File entry Ent7 ; SD card - File entry Ent8 ; SD card - File entry Ent9 ; SD card - File entry Ent10 ; SD card - File entry validroot ; SD card - Number of valid files in root directory endc ;------------------------------------------------------------------------------- ;------------------------------ Define Symbols ------------------------------- ;------------------------------------------------------------------------------- #define LCDen LATE, 1, 1 #define LCDrw LATC, 2, 1 #define LCDrs LATC, 1, 1 #define Row1 PORTB, 7, 1 #define Row2 PORTB, 6, 1 #define Row3 PORTB, 5, 1 #define Row4 PORTB, 4, 1 #define Col1 LATB, 3, 1 #define Col2 LATB, 2, 1 #define Col3 LATB, 1, 1 #define Col4 LATB, 0, 1 #define MCS LATE, 2, 1 #define SDPS PORTA, 4, 1 #define SDCS LATA, 0, 1 #define BSDI PORTA, 3, 1 #define BSDO LATA, 1, 1 #define BCLK LATA, 2, 1 ;------------------------------------------------------------------------------- ;------------------------------- Program Code -------------------------------- ;------------------------------------------------------------------------------- ORG 0x0 ; Reset Vector goto Init ORG 0x0008 ; High Priority Interrupt Vector goto HintVect ORG 0x0018 ; Low Priority Interrupt Vector ;------------------------------------------------------------------------------- ;----------------------- Low Priority Interrupt Vector ----------------------- ;------------------------------------------------------------------------------- LintVect retfie ;------------------------------------------------------------------------------- ;---------------------- High Priority Interrupt Vector ----------------------- ;------------------------------------------------------------------------------- HintVect retfie ;------------------------------------------------------------------------------- ;-------------------------- Initialisation of Ports -------------------------- ;------------------------------------------------------------------------------- Init movlb d'15' ; Set BSR to bank 15 clrf ADCON0 ; Turn off analogue module movlw 00001111b movwf ADCON1 ; Configure all pins as digital movlw 00000111b movwf CMCON ; Turn off comparators movlw 00011000b movwf TRISA, 1 movlw 11110000b ; PortB 7-4 inputs, 3-0 outputs movwf TRISB, 1 movlw 11010000b movwf TRISC, 1 clrf TRISD ; Set all ports as outputs clrf TRISE, 1 movlw 01110000b movwf OSCCON ; 8MHz Internal oscillator movlw 01000000b movwf OSCTUNE ; Enable PLL ; 32MHz with PLL bsf EECON1, WREN, 1 ; Enable write mode EEPROM / FLASH movlw 00001000b movwf BAUDCON, 1 ; Set BRG16 movlw 0x40 movwf SPBRG, 1 movlw 0x03 ; Set SPBRGH:SPBRG to 832 movwf SPBRGH, 1 movlw 10010000b movwf RCSTA, 1 movlw 00100100b movwf TXSTA, 1 ;bsf RCON, IPEN, 1 ; Turn on Priority Interrupts ;bsf PIE1, TXIE, 1 ; Turn on TX Interrupt ;bsf IPR1, TXIP, 1 ; Set TX to High Priority ;movlw 00000111b ;movwf T0CON, 1 ; Set internal timer, 256 prescaler, 16 bit ;;bsf INTCON, TMR0IE, 1 ;bsf INTCON2, TMR0IP, 1 call LCDinit ;------------------------------------------------------------------------------- ;----------------------------- SPI Initialisation ---------------------------- ;------------------------------------------------------------------------------- movlw 00110000b ; Serial port enable, 8MHz movwf SSPCON1, 1 ; Clock polarity idle high bcf SSPSTAT, CKE, 1 bsf MCS ; Deselect chip 1 ;------------------------------------------------------------------------------- ;------------------------------- Main Program -------------------------------- ;------------------------------------------------------------------------------- call ChipErase ;------------------------------------------------------------------------------- ;------------------------------- Main Program -------------------------------- ;------------------------------------------------------------------------------- Main call Message1 ; "Insert SD Card" call SDinit ; Initialise SD Card call Message2 ; "SD Card Initialised" call sec_2delay ; 2 second delay call Message7 ; "Finding Adress Offset" call SDoffset ; find Address offset call sec_2delay ; 2 second delay call Message8 ; "Address offset" call BCDdisp ; Display offset number call sec_2delay ; 2 second delay call Message3 ; "Finding Root Folder" call SDroot ; Find root folder call sec_2delay ; 2 second delay call Message4 ; "Root Folder Found" call BCDdisp ; Display root address call sec_2delay ; 2 second delay call WriteDir movlw h'20' movwf Ent3, 0 movwf Ent4, 0 movwf Ent5, 0 movwf Ent6, 0 movwf Ent7, 0 movlw "B" movwf Ent8, 0 movlw "M" movwf Ent9, 0 movlw "P" movwf Ent10, 0 movlw "0" movwf Ent0, 0 movlw "0" movwf Ent1, 0 movlw "8" movwf Ent2, 0 movf sdadrser8, w, 0 movwf Adr8, 0 movf sdadrser16, w, 0 movwf Adr16, 0 movf sdadrser24, w, 0 movwf Adr24, 0 movf sdadrser32, w, 0 movwf Adr32, 0 call Message5 ; "Locating File" call ReadDir ; Find entry location call sec_2delay ; 2 second delay call Message6 ; "File Located" call ReadSD ; Should display BM8 if found correctly call SPIR call LCDsend call SPIR call LCDsend call SPIR call LCDsend goto $ ;------------------------------------------------------------------------------- ;------------------------ Clock data into memory chip ------------------------ ;------------------------------------------------------------------------------- MEMSPI call SPI decfsz temp5, f, 0 return movwf MEMtemp, 0 movlw d'128' movwf temp5, 0 movf MEMtemp, w, 0 decfsz temp6, f, 0 return bsf MCS nop nop bcf MCS call memstatus bsf MCS incf Adr2, f, 0 btfsc STATUS, C, 1 incf Adr3, f, 0 WrtMEM bcf MCS movlw 00000110b ; Write enable call SPI bsf MCS nop nop bcf MCS movlw 00000010b ; Start 256 byte write call SPI movf Adr3, w call SPI movf Adr2, w call SPI movf Adr1, w call SPI call SPIF movlw d'128' movwf temp5, 0 movlw d'2' movwf temp6, 0 return ChipErase bcf MCS movlw 00000110b ; Write enable call SPI bsf MCS nop nop bcf MCS movlw 11000111b ; Chip erase call SPI bsf MCS nop nop bcf MCS call memstatus bsf MCS return memstatus movlw 00000101b ; Check status 1 call SPI cst call SPIF btfsc WREG, 0, 1 ; Check if busy goto cst return ;------------------------------------------------------------------------------- ;--------------------------- Send and Receive Serial -------------------------- ;------------------------------------------------------------------------------- SPIF movlw 0x00 SPI movwf temp, 0 movf SSPBUF, w, 1 ; Clear buffer full flag movf temp, w, 0 movwf SSPBUF, 1 ; Send data SPI_a btfss SSPSTAT, BF, 1 goto SPI_a ; Check if sent movf SSPBUF, w, 1 return ;------------------------------------------------------------------------------- ;---------------------------------- Keypad ----------------------------------- ;------------------------------------------------------------------------------- Keyscan bcf Col1 bcf Col2 bcf Col3 ; Check if a key has been pressed bcf Col4 btfss Row1 goto scanprocess btfss Row2 goto scanprocess btfss Row3 goto scanprocess btfsc Row4 goto Keyscan scanprocess bcf Col1 ; Check which key has been pressed bsf Col2 bsf Col3 bsf Col4 movlw d'1' call Rscan bsf Col1 movlw d'2' bcf Col2 call Rscan bsf Col2 movlw d'3' bcf Col3 call Rscan bsf Col3 movlw d'4' bcf Col4 call Rscan bsf Col4 goto Keyscan Rscan btfss Row1 ; Which row? goto R1set btfss Row2 goto R2set btfss Row3 goto R3set btfss Row4 goto R4set return R1set addlw d'0' goto clrct R2set addlw d'4' goto clrct R3set addlw d'8' goto clrct R4set addlw d'12' clrct movwf temp1, 0 decf STKPTR, f, 1 Keynot call d50ms ; 50ms debounce bcf Col1 bcf Col2 bcf Col3 ; Check when key is depressed bcf Col4 btfss Row1 goto Keynot btfss Row2 goto Keynot btfss Row3 goto Keynot btfss Row4 goto Keynot movlw LOW table ; take low table address addwf temp1, w, 0 ; add to temp1, acts as an offset movwf TBLPTRL, 1 ; Move low table pointer clrf TBLPTRH movlw HIGH table addwfc TBLPTRH, f, 1 ; add high table address and carry ; if there was one from last addwf clrf TBLPTRU movlw UPPER table ; do same for upper table address addwf TBLPTRU, f, 1 tblrd * ; Read the contents via TBLPTR movf TABLAT, w, 1 ; Move results into working register return table db "1", "1", "2", "3", "A", "4", "5", "6" ; our data table db "B", "7", "8", "9", "C", "*", "0", "#" db "D" ;------------------------------------------------------------------------------- ;----------------------------- LCD Initialisation ---------------------------- ;------------------------------------------------------------------------------- LCDinit call d50ms ;Function Set movlw 00111000b ;8-bit mode, 2 lines, 5x7 matrix call LCDinst ;Display on / off movlw 00001100b ;Display on, Cursor off, Blink off call LCDinst ;Entry Mode Set movlw 00000110b ;Increment, Display shifted call LCDinst ;Cursor or display shift movlw 00010000b ;Display Shift call LCDinst ;Clear Screen movlw 00000001b ; Clear screen call LCDinst return ;------------------------------------------------------------------------------- ;----------------------------- LCD Character Send ---------------------------- ;------------------------------------------------------------------------------- LCDsend movlb d'15' ; Ensure BSR is FSR banking bsf LCDrs ; Data mode bcf LCDrw ; Write mode call sndt ; Send data return ;------------------------------------------------------------------------------- ;------------------------- LCD Character Digit Send -------------------------- ;------------------------------------------------------------------------------- LCDdigit movlb d'15' ; Ensure BSR is FSR banking bsf LCDrs ; Data mode bcf LCDrw ; Write mode addlw d'48' call sndt ; Send data return ;------------------------------------------------------------------------------- ;---------------------------- LCD Instruction Send --------------------------- ;------------------------------------------------------------------------------- LCDinst movlb d'15' ; Ensure BSR is FSR banking bcf LCDrs ; Instruction mode bcf LCDrw ; Write mode call sndt ; Send data call d50ms return ;------------------------------------------------------------------------------- ;--------------------------------- Bus Send --------------------------------- ;------------------------------------------------------------------------------- sndt movwf LATD, 1 ; Place into LCD bus nop bsf LCDen nop nop nop bcf LCDen goto micro100 ;------------------------------------------------------------------------------- ;------------------------------- LCD Messages -------------------------------- ;------------------------------------------------------------------------------- Message1 movlw 00000001b ; Clear screen call LCDinst call d50ms movlw LOW messtab1 movwf TBLPTRL, 1 movlw HIGH messtab1 movwf TBLPTRH, 1 movlw UPPER messtab1 movwf TBLPTRU, 1 mess1loop tblrd *+ movf TABLAT, w, 1 xorlw "~" btfsc STATUS, Z, 1 return movf TABLAT, w, 1 call LCDsend goto mess1loop messtab1 db " Insert SD Card~" ; "~" indicates end of message Message2 movlw 00000001b ; Clear screen call LCDinst call d50ms movlw LOW messtab2 movwf TBLPTRL, 1 movlw HIGH messtab2 movwf TBLPTRH, 1 movlw UPPER messtab2 movwf TBLPTRU, 1 mess2loop tblrd *+ movf TABLAT, w, 1 xorlw "~" btfsc STATUS, Z, 1 return movf TABLAT, w, 1 call LCDsend goto mess2loop messtab2 db "SD Card Initialised~" ; "~" indicates end of message Message3 movlw 00000001b ; Clear screen call LCDinst call d50ms movlw LOW messtab3 movwf TBLPTRL, 1 movlw HIGH messtab3 movwf TBLPTRH, 1 movlw UPPER messtab3 movwf TBLPTRU, 1 mess3loop tblrd *+ movf TABLAT, w, 1 xorlw "~" btfsc STATUS, Z, 1 return movf TABLAT, w, 1 call LCDsend goto mess3loop messtab3 db "Finding Root Folder~" ; "~" indicates end of message Message4 movlw 00000001b ; Clear screen call LCDinst call d50ms movlw LOW messtab4 movwf TBLPTRL, 1 movlw HIGH messtab4 movwf TBLPTRH, 1 movlw UPPER messtab4 movwf TBLPTRU, 1 mess4loop tblrd *+ movf TABLAT, w, 1 xorlw "~" btfsc STATUS, Z, 1 return movf TABLAT, w, 1 call LCDsend goto mess4loop messtab4 db " Root Folder Found Address ~" ; "~" indicates end of message Message5 movlw 00000001b ; Clear screen call LCDinst call d50ms movlw LOW messtab5 movwf TBLPTRL, 1 movlw HIGH messtab5 movwf TBLPTRH, 1 movlw UPPER messtab5 movwf TBLPTRU, 1 mess5loop tblrd *+ movf TABLAT, w, 1 xorlw "~" btfsc STATUS, Z, 1 return movf TABLAT, w, 1 call LCDsend goto mess5loop messtab5 db " Locating File~" ; "~" indicates end of message Message6 movlw 00000001b ; Clear screen call LCDinst call d50ms movlw LOW messtab6 movwf TBLPTRL, 1 movlw HIGH messtab6 movwf TBLPTRH, 1 movlw UPPER messtab6 movwf TBLPTRU, 1 mess6loop tblrd *+ movf TABLAT, w, 1 xorlw "~" btfsc STATUS, Z, 1 return movf TABLAT, w, 1 call LCDsend goto mess6loop messtab6 db " File Located ~" ; "~" indicates end of message Message7 movlw 00000001b ; Clear screen call LCDinst call d50ms movlw LOW messtab7 movwf TBLPTRL, 1 movlw HIGH messtab7 movwf TBLPTRH, 1 movlw UPPER messtab7 movwf TBLPTRU, 1 mess7loop tblrd *+ movf TABLAT, w, 1 xorlw "~" btfsc STATUS, Z, 1 return movf TABLAT, w, 1 call LCDsend goto mess7loop messtab7 db " Finding Address Offset~" ; "~" indicates end of message Message8 movlw 00000001b ; Clear screen call LCDinst call d50ms movlw LOW messtab8 movwf TBLPTRL, 1 movlw HIGH messtab8 movwf TBLPTRH, 1 movlw UPPER messtab8 movwf TBLPTRU, 1 mess8loop tblrd *+ movf TABLAT, w, 1 xorlw "~" btfsc STATUS, Z, 1 return movf TABLAT, w, 1 call LCDsend goto mess8loop messtab8 db " Address Offset ~" ; "~" indicates end of message ;------------------------------------------------------------------- ;------------------------------------------------------------------------------- ;------------------------------ Delay Routines ------------------------------- ;------------------------------------------------------------------------------- sec_2delay call delay call delay call delay call delay call delay call delay call delay call delay return delay movlw d'25' ; 125ns 0.25 second delay movwf b0_temp3, 0 ; 125ns nop ; 125ns label_3 movlw d'40' ; 125ns movwf b0_temp2, 0 ; 125ns nop ; 125ns nop ; 125ns label_1 movlw d'249' ; 125ns movwf b0_temp, 0 ; 125ns nop ; 125ns nop ; 125ns label_2 nop ; 125ns nop ; 125ns nop ; 125ns nop ; 125ns nop ; 125ns decfsz b0_temp, f, 0 ; 125ns goto label_2 ; 250ns (1us total inner loop) ; 125ns decfsz b0_temp2, f, 0 ; 125ns goto label_1 ; 250ns ; 125ns decfsz b0_temp3, f, 0 ; 125ns goto label_3 ; 250ns return d50ms movlw d'1' ; 50ms delay movwf b0_temp3, 0 goto label_3 micro100 movlw d'100' ; 100us delay movwf b0_temp, 0 label_4 nop ; 125ns nop ; 125ns nop ; 125ns nop ; 125ns nop ; 125ns decfsz b0_temp, f, 0 ; 125ns goto label_4 ; 250ns (1us total inner loop) return ;------------------------------------------------------------------------------- ;------------------------------ EEPROM Routines ------------------------------ ;------------------------------------------------------------------------------- Eread movff E_adr, EEADR ; Move address to pointer bsf EECON1, RD, 1 ; Start read movff EEDATA, E_data ; Move read data to working file return Ewrite movff E_data, EEDATA ; Data to be written movff E_adr, EEADR ; Address pointer bcf EECON1, EEPGD, 1 ; Point to data mode bcf EECON1, CFGS, 1 ; Access EEPROM btfsc EECON1, WR, 1 ; Check to see if a write is still goto $-2 ; in progress movlw 0x55 movwf EECON2, 1 movlw 0xAA movwf EECON2, 1 ; Required sequence bsf EECON1, WR, 1 ; Start write return ;------------------------------------------------------------------------------- ;------------------------------- FLASH Routines ------------------------------ ;------------------------------------------------------------------------------- F_erase bsf EECON1, EEPGD, 1 ; Flash pointer bcf EECON1, CFGS, 1 ; Access Flash bsf EECON1, WREN, 1 ; Write enabled bsf EECON1, FREE, 1 ; Erase 64 byte row enable btfsc EECON1, WR, 1 ; Check to see if a write or goto $-2 ; erase is still in progress movlw 0x55 movwf EECON2, 1 movlw 0xAA movwf EECON2, 1 ; Required sequence bsf EECON1, WR, 1 ; Start erase cycle return F_write btfsc EECON1, WR, 1 ; Check to see if a write or goto $-2 ; erase is still in progress movlw d'32' movwf tmpctr, 0 ; 32 loop counter lptab movff POSTINC0, TABLAT ; Move RAM to table latch tblwt *+ ; Store and then increment pointer decfsz tmpctr, f, 0 ; Decrement loop counter goto lptab tblrd *- ; Dummy TBLPTR decrement bsf EECON1, EEPGD, 1 ; Flash pointer bcf EECON1, CFGS, 1 ; Access Flash bsf EECON1, WREN, 1 ; Write enabled movlw 0x55 movwf EECON2, 1 movlw 0xAA movwf EECON2, 1 ; Required sequence bsf EECON1, WR, 1 ; Start flash write cycle return ;------------------------------------------------------------------------------- ;---------------------------------- Analogue --------------------------------- ;------------------------------------------------------------------------------- bsf TRISA, 0, 1 ; Set RA0 to input ADC movlw 10000010b movwf ADCON2, 1 ; Set 1/32 speed, no delay movlw 00001110b movwf ADCON1, 1 ; Set RA0, AN0 analogue input movlw 00000001b movwf ADCON0, 1 ; Channel AN0, enable module bsf ADCON0, GO, 1 ; Start Reading btfsc ADCON0, GO, 1 ; Reading done? goto $-2 return ;yes done ;------------------------------------------------------------------------------- ;-------------------------- Binary to Decimal Routine ------------------------- ;------------------------------------------------------------------------------- BCD clrf digit1, 0 clrf digit2, 0 clrf digit3, 0 clrf digit4, 0 clrf digit5, 0 clrf digit6, 0 clrf digit7, 0 clrf digit8, 0 clrf digit9, 0 clrf digit10, 0 movlw d'32' ;16 bits to do movwf bcdtmp1, 0 bcf STATUS, C bitlp rlcf count0, f, 0 ;Shift msb into carry rlcf count1, f, 0 rlcf count2, f, 0 rlcf count3, f, 0 movlw LOW digit1 movwf FSR1L, 1 ;Pointer to digits movlw HIGH digit1 movwf FSR1H, 1 ;Pointer to digits movlw d'10' ;10 digits to do movwf bcdtmp2, 0 adjlp rlcf INDF1, f, 1 ;Shift digit 1 bit left movlw d'10' subwf INDF1, w, 1 ;Check and adjust for decimal overflow btfsc STATUS, C ;Postinc affects both fsrl and fsrh movwf POSTINC1, 1 btfss STATUS, C movf POSTINC1, w, 1 ;This is just to postinc, decfsz bcdtmp2, f, 0 goto adjlp decfsz bcdtmp1, f, 0 ;Next bit goto bitlp return ;------------------------------------------------------------------------------- ;---------------------------- Display Digits to LCD -------------------------- ;------------------------------------------------------------------------------- BCDdisp call BCD movf digit10, w, 0 addlw d'0' btfss STATUS, Z, 1 goto skpBCDdig1 movf digit9, w, 0 addlw d'0' btfss STATUS, Z, 1 goto skpBCDdig2 movf digit8, w, 0 addlw d'0' btfss STATUS, Z, 1 goto skpBCDdig3 movf digit7, w, 0 addlw d'0' btfss STATUS, Z, 1 goto skpBCDdig4 movf digit6, w, 0 addlw d'0' btfss STATUS, Z, 1 goto skpBCDdig5 movf digit5, w, 0 addlw d'0' btfss STATUS, Z, 1 goto skpBCDdig6 movf digit4, w, 0 addlw d'0' btfss STATUS, Z, 1 goto skpBCDdig7 movf digit3, w, 0 addlw d'0' btfss STATUS, Z, 1 goto skpBCDdig8 movf digit2, w, 0 addlw d'0' btfss STATUS, Z, 1 goto skpBCDdig9 goto skpBCDdig10 skpBCDdig1 movf digit10, w, 0 addlw d'48' call LCDsend skpBCDdig2 movf digit9, w, 0 addlw d'48' call LCDsend skpBCDdig3 movf digit8, w, 0 addlw d'48' call LCDsend skpBCDdig4 movf digit7, w, 0 addlw d'48' call LCDsend skpBCDdig5 movf digit6, w, 0 addlw d'48' call LCDsend skpBCDdig6 movf digit5, w, 0 addlw d'48' call LCDsend skpBCDdig7 movf digit4, w, 0 addlw d'48' call LCDsend skpBCDdig8 movf digit3, w, 0 addlw d'48' call LCDsend skpBCDdig9 movf digit2, w, 0 addlw d'48' call LCDsend skpBCDdig10 movf digit1, w, 0 addlw d'48' call LCDsend return ;------------------------------------------------------------------------------- ;-------------------------------- Table Fetch -------------------------------- ;------------------------------------------------------------------------------- fetch movlw UPPER datatable movwf PCLATU ; Place datatable address to UPPER movlw HIGH datatable movwf PCLATH ; Place datatable address to HIGH movf offset, w, 0 ; Add offset to PCL, place result addwf PCL, w, 1 ; in working file, PCL not modified btfsc STATUS, C incf PCLATH, f, 1 btfsc STATUS, C ; Any carries then modify higher PCL incf PCLATU, f, 1 ; registers movf offset, w, 0 addwf PCL, f, 1 ; Modify PCL and jumo to datatable datatable movlw d'20' return ;------------------------------------------------------------------------------- ;----------------------------- 16 x 16 Multiply ------------------------------ ;------------------------------------------------------------------------------- MUL16 movf arg1L, w, 0 mulwf arg2L, 0 movff PRODL, result0 movff PRODH, result1 movf arg1H, w, 0 mulwf arg2H, 0 movff PRODL, result2 movff PRODH, result3 movf arg1L, w, 0 mulwf arg2H, 0 movf PRODL, w, 1 addwf result1, f, 0 movf PRODH, w, 1 addwfc result2, f, 0 clrf WREG, 1 addwfc result3, f, 0 movf arg1H, w, 0 mulwf arg2L, 0 movf PRODL, w, 1 addwf result1, f, 0 movf PRODH, w, 1 addwfc result2, f, 0 clrf WREG, 1 addwfc result3, f, 0 return ;------------------------------------------------------------------------------- ;------------------------------- 32 / 16 Divide ------------------------------ ;------------------------------------------------------------------------------- Divide clrf R0 clrf R1 clrf R2 movlw d'32' ; 32 loops for 32-bit movwf lptmp Div_2 bcf STATUS, C rlcf Word0, f, 0 rlcf Word1, f, 0 rlcf Word2, f, 0 rlcf Word3, f, 0 rlcf R2, f, 0 rlcf R1, f, 0 rlcf R0, f, 0 movf DenL, w, 0 subwf R2, f, 0 movf DenH, w, 0 subwfb R1, w, 0 bc Div_4 tstfsz R0, 0 goto Div_3 movf DenL, w, 0 addwf R2, f, 0 goto Div_5 Div_3 decf R0, f, 0 Div_4 movwf R1, 0 bsf Word0, 0, 0 Div_5 decfsz lptmp, f, 0 goto Div_2 ; Go do next loop return ; Finished our divide routine ;------------------------------------------------------------------------------- ;----------------------------- Initialise SD Card ---------------------------- ;------------------------------------------------------------------------------- SDinit btfsc SDPS ; Check if card Inserted goto SDinit call sec_2delay ; Delay of 2 seconds notint bsf SDCS ; Deselect SD Card call SPID call SPID ; Send a total of 80 clock pulses call SPID call SPID call SPID ; SPIB calls a bit-banged call SPID ; version of the SPI module call SPID call SPID ; SPID calls a bit-banged call SPID ; version of the SPI module call SPID ; except 0xFF is sent ;------------------------------------------------------------------------------- bcf SDCS ; Select SD Card movlw 01000000b ; Command 0, software reset call SPIB call SPIZ call SPIZ call SPIZ call SPIZ movlw 10010101b ; CRC call SPIB call SPID ; NCR call SPID ; Send to Receive Response xorlw 00000001b btfss STATUS, Z, 1 goto notint ; An error?, try again bsf SDCS ; Deselect SD Card ;------------------------------------------------------------------------------- bcf SDCS ; Select SD Card movlw 01001000b ; Command 8, check card type call SPIB call SPIZ call SPIZ movlw d'1' call SPIB movlw 0xAA ; AA call SPIB movlw 10000111b ; CRC call SPIB call SPID ; NCR call SPID ; NCR xorlw 00000001b btfss STATUS, Z, 1 goto notint call SPID ; Dummy data call SPID ; Dummy data call SPID ; Dummy data call SPID ; Dummy data xorlw 10101010b ; Result AA - SD Version 2 btfss STATUS, Z, 1 goto notint bsf SDCS ; Deselect SD Card ;------------------------------------------------------------------------------- loop55 bcf SDCS ; Select SD Card movlw 01110111b ; Command ACMD41, initialis card call SPIB ; for SPI use call SPIZ call SPIZ call SPIZ call SPIZ call SPID ; CRC, does not need to be valid call SPID ; NCR call SPID ; Dummy data addlw d'0' btfsc STATUS, Z, 1 goto done movlw 01101001b ; Command 55 call SPIB movlw 01000000b call SPIB call SPIZ call SPIZ call SPIZ call SPID ; CRC, does not need to be valid call SPID ; NCR call SPID ; Dummy data bsf SDCS ; Deselect SD Card addlw d'0' btfss STATUS, Z, 1 goto loop55 done bsf SDCS ; Deselect SD Card return ;------------------------------------------------------------------------------- ;----------------------------- Single block write SD ------------------------- ;------------------------------------------------------------------------------- WriteSD bcf SDCS ; Select SD Card movlw 01011000b ; Command 24, single block write call SPIB movf Adr32, w, 0 call SPIB movf Adr24, w, 0 call SPIB movf Adr16, w, 0 call SPIB movf Adr8, w, 0 call SPIB call SPID ; CRC call SPID ; NCR wlpagain call SPID ; Check response addlw 00000000b btfss STATUS, Z, 1 goto wlpagain call SPID ; Dummy byte movlw 11111110b call SPIB ; Start Token movlw d'128' movwf temp7, 0 movlw d'4' movwf temp8, 0 SPIW call SPIF call SPIB decfsz temp7, f, 0 goto SPIW movlw d'128' movwf temp7, 0 decfsz temp8, f, 0 goto SPIW call SPID ; CRC call SPID ; CRC wchkst call SPID xorlw 11100101b ; Data response btfss STATUS, Z, 1 goto wchkst call SPID bsf SDCS ; Deselect SD Card call SPID bcf SDCS ; Select SD Card wchkst_2 call SPID ; Clock dummy data until write xorlw 11111111b ; is complete btfss STATUS, Z, 1 goto wchkst_2 bsf SDCS ; Deselect SD Card return ;------------------------------------------------------------------------------- ;-------------------- Read Specific Location From SD Card -------------------- ;------------------------------------------------------------------------------- ReadSD bcf SDCS ; Select SD Card movlw b'01010010' ; Command 18, Multiple read call SPIB movf Adr32, w call SPIB movf Adr24, w call SPIB movf Adr16, w call SPIB movf Adr8, w call SPIB movlw d'1' ; Checksum call SPIB call SPID call SPID ; R1 response lpagain call SPID ; Check if start token received xorlw 11111110b btfss STATUS, Z, 1 goto lpagain movlw d'4' movwf spbitH, 0 movlw d'128' movwf spbitL, 0 return ;------------------------------------------------------------------------------- ;------------------------------ SD Card End Read ----------------------------- ;------------------------------------------------------------------------------- Edcmd movlw 01001100b ; Command 12 call SPIB movlw d'0' call SPIB movlw d'0' call SPIB movlw d'0' call SPIB movlw d'0' call SPIB movlw d'1' call SPIB call SPID lpend call SPID addlw d'0' btfss STATUS, Z, 1 goto lpend bsf SDCS ; Deselect SD Card return ;------------------------------------------------------------------------------- ;----------------------- Read 512 bytes, increment program --------------------- ;------------------------------------------------------------------------------- SPIR call SPID ; Check we only read 512 bytes before discarding decfsz spbitL, f, 0 ; CRC and check for start token return movwf SPRtemp, 0 movlw d'128' movwf spbitL, 0 movf SPRtemp, w, 0 decfsz spbitH, f, 0 return movlw d'4' movwf spbitH, 0 call SPID ; CRC call SPID ; CRC lptoken call SPID ; Check for start token xorlw 11111110b btfss STATUS, Z, 1 goto lptoken movf SPRtemp, w, 0 return ;------------------------------------------------------------------------------- ;-------------------- Find boot sector and root directory -------------------- ;------------------------------------------------------------------------------- SDoffset clrf Adr8, 0 clrf Adr16, 0 clrf Adr24, 0 clrf Adr32, 0 call ReadSD movlw d'128' movwf temp1, 0 sdr_1 call SPIR decfsz temp1, f, 0 goto sdr_1 movlw d'128' movwf temp1, 0 sdr_2 call SPIR decfsz temp1, f, 0 goto sdr_2 movlw d'128' movwf temp1, 0 sdr_3 call SPIR decfsz temp1, f, 0 goto sdr_3 movlw d'70' movwf temp1, 0 sdr_4 call SPIR decfsz temp1, f, 0 goto sdr_4 call SPIR movwf sdadrser8, 0 movwf count0, 0 call SPIR movwf sdadrser16, 0 movwf count1, 0 call SPIR movwf sdadrser24, 0 movwf count2, 0 call SPIR movwf sdadrser32, 0 ; We now have boot sector offset movwf count3, 0 call Edcmd ; End read return SDroot movf sdadrser8, w, 0 movwf Adr8, 0 movf sdadrser16, w, 0 movwf Adr16, 0 movf sdadrser24, w, 0 movwf Adr24, 0 movf sdadrser32, w, 0 movwf Adr32, 0 call ReadSD ; We are now reading boot sector call SPIR call SPIR call SPIR call SPIR call SPIR call SPIR call SPIR call SPIR call SPIR call SPIR call SPIR call SPIR movwf bytesect8, 0 call SPIR movwf bytesect16, 0 call SPIR movwf sectclus, 0 call SPIR movwf ressect8, 0 call SPIR movwf ressect16, 0 call SPIR movwf numFAT, 0 movlw d'19' movwf temp1, 0 sdr_5 call SPIR decfsz temp1, f, 0 goto sdr_5 call SPIR movwf sectFAT8, 0 call SPIR movwf sectFAT16, 0 call SPIR movwf sectFAT24, 0 call SPIR movwf sectFAT32, 0 call Edcmd ;end of boot sector read. ; root directory = boot sector offset + reserved sectors + (fat number * sectors per FAT) ; sectors per FAT will always bcf STATUS, C, 1 rlcf sectFAT8, f, 0 rlcf sectFAT16, f, 0 rlcf sectFAT24, f, 0 rlcf sectFAT32, f, 0 movf sectFAT8, w, 0 addwf sdadrser8, f, 0 btfss STATUS, C, 1 goto sdr_6 incf sdadrser16, f, 0 btfss STATUS, C, 1 goto sdr_6 incf sdadrser24, f, 0 btfsc STATUS, C, 1 incf sdadrser32, f, 0 sdr_6 movf sectFAT16, w, 0 addwf sdadrser16, f, 0 btfss STATUS, C, 1 goto sdr_7 incf sdadrser24, f, 0 btfsc STATUS, C, 1 incf sdadrser32, f, 0 sdr_7 movf sectFAT24, w, 0 addwf sdadrser24, f, 0 btfsc STATUS, C, 1 incf sdadrser32, f, 0 movf sectFAT32, w, 0 addwf sdadrser32, f, 0 movf ressect8, w, 0 addwf sdadrser8, f, 0 btfss STATUS, C, 1 goto sdr_8 incf sdadrser16, f, 0 btfss STATUS, C, 1 goto sdr_8 incf sdadrser24, f, 0 btfsc STATUS, C, 1 incf sdadrser32, f, 0 sdr_8 movf ressect16, w, 0 addwf sdadrser16, f, 0 btfss STATUS, C, 1 goto sdr_9 incf sdadrser24, f, 0 btfsc STATUS, C, 1 incf sdadrser32, f, 0 sdr_9 ; sdadrser variables now have the location of the root directory. movf sdadrser8, w, 0 movwf Adr8, 0 movwf count0, 0 movf sdadrser16, w, 0 movwf Adr16, 0 movwf count1, 0 movf sdadrser24, w, 0 movwf Adr24, 0 movwf count2, 0 movf sdadrser32, w, 0 movwf Adr32, 0 movwf count3, 0 return ;------------------------------------------------------------------------------- ;------------------------------- Bit Bang SPI --------------------------------- ;------------------------------------------------------------------------------- SPIZ movlw d'0' goto SPIB SPID movlw d'255' SPIB movwf temp2, 0 clrf SPItemp, 0 bsf BCLK bcf BSDO btfsc temp2, 7, 0 bsf BSDO bcf BCLK bsf BCLK btfsc BSDI bsf SPItemp, 7, 0 bcf BSDO btfsc temp2, 6, 0 bsf BSDO bcf BCLK bsf BCLK btfsc BSDI bsf SPItemp, 6, 0 bcf BSDO btfsc temp2, 5, 0 bsf BSDO bcf BCLK bsf BCLK btfsc BSDI bsf SPItemp, 5, 0 bcf BSDO btfsc temp2, 4, 0 bsf BSDO bcf BCLK bsf BCLK btfsc BSDI bsf SPItemp, 4, 0 bcf BSDO btfsc temp2, 3, 0 bsf BSDO bcf BCLK bsf BCLK btfsc BSDI bsf SPItemp, 3, 0 bcf BSDO btfsc temp2, 2, 0 bsf BSDO bcf BCLK bsf BCLK btfsc BSDI bsf SPItemp, 2, 0 bcf BSDO btfsc temp2, 1, 0 bsf BSDO bcf BCLK bsf BCLK btfsc BSDI bsf SPItemp, 1, 0 bcf BSDO btfsc temp2, 0, 0 bsf BSDO bcf BCLK bsf BCLK btfsc BSDI bsf SPItemp, 0, 0 bcf BSDO movf SPItemp, w, 0 return ;------------------------------------------------------------------------------- ;------------------------------- Read Directory ------------------------------ ;------------------------------------------------------------------------------- ReadDir call ReadSD ReadDir_1 movlw d'31' movwf temp1, 0 call SPIR xorlw 0xE5 btfsc STATUS, Z, 1 goto delent ; If set we want to skip to next entry movf SPItemp, w, 0 xorwf Ent0, w, 0 btfss STATUS, Z, 1 goto delent decf temp1, f, 0 call SPIR xorwf Ent1, w, 0 btfss STATUS, Z, 1 goto delent decf temp1, f, 0 call SPIR xorwf Ent2, w, 0 btfss STATUS, Z, 1 goto delent decf temp1, f, 0 call SPIR xorwf Ent3, w, 0 btfss STATUS, Z, 1 goto delent decf temp1, f, 0 call SPIR xorwf Ent4, w, 0 btfss STATUS, Z, 1 goto delent decf temp1, f, 0 call SPIR xorwf Ent5, w, 0 btfss STATUS, Z, 1 goto delent decf temp1, f, 0 call SPIR xorwf Ent6, w, 0 btfss STATUS, Z, 1 goto delent decf temp1, f, 0 call SPIR xorwf Ent7, w, 0 btfss STATUS, Z, 1 goto delent decf temp1, f, 0 call SPIR xorwf Ent8, w, 0 btfss STATUS, Z, 1 goto delent decf temp1, f, 0 call SPIR xorwf Ent9, w, 0 btfss STATUS, Z, 1 goto delent decf temp1, f, 0 call SPIR xorwf Ent10, w, 0 btfss STATUS, Z, 1 goto delent ; Our entry matches call SPIR ; Discard attributes call SPIR ; Discard reserved call SPIR ; Discard file creation time call SPIR ; Discard file creation time call SPIR ; Discard file creation time call SPIR ; Discard file creation date call SPIR ; Discard file creation date call SPIR ; Discard file access date call SPIR ; Discard file access date call SPIR movwf Adr24, 0; High cluster offset call SPIR movwf Adr32, 0; High cluster offset call SPIR ; Discard file modification time call SPIR ; Discard file modification time call SPIR ; Discard file modification date call SPIR ; Discard file modification date call SPIR movwf Adr8, 0 ; Low cluster offset call SPIR movwf Adr16, 0; Low cluster offset call Edcmd ; End read command movlw d'2' ; Minus 2 as our root directory starts at 2 subwf Adr8, 0 btfsc STATUS, C, 1 goto nxtmul movlw d'1' subwf Adr16, 0 btfsc STATUS, C, 1 goto nxtmul movlw d'1' subwf Adr24, 0 btfsc STATUS, C, 1 goto nxtmul decf Adr32, f, 0 nxtmul bcf STATUS, C, 1 ; We have our offset, it needs to be ; multiplied by the number of sectors ; per cluster. rlcf Adr8, f, 0 ; 2 sectors per cluster rlcf Adr16, f, 0 rlcf Adr24, f, 0 rlcf Adr32, f, 0 movf sectclus, w, 0 xorlw d'2' btfsc STATUS, Z, 1 goto adrtoft rlcf Adr8, f, 0 ; 4 sectors per cluster rlcf Adr16, f, 0 rlcf Adr24, f, 0 rlcf Adr32, f, 0 movf sectclus, w, 0 xorlw d'4' btfsc STATUS, Z, 1 goto adrtoft rlcf Adr8, f, 0 ; 8 sectors per cluster rlcf Adr16, f, 0 rlcf Adr24, f, 0 rlcf Adr32, f, 0 movf sectclus, w, 0 xorlw d'8' btfsc STATUS, Z, 1 goto adrtoft rlcf Adr8, f, 0 ; 16 sectors per cluster rlcf Adr16, f, 0 rlcf Adr24, f, 0 rlcf Adr32, f, 0 movf sectclus, w, 0 xorlw d'16' btfsc STATUS, Z, 1 goto adrtoft rlcf Adr8, f, 0 ; 32 sectors per cluster rlcf Adr16, f, 0 rlcf Adr24, f, 0 rlcf Adr32, f, 0 movf sectclus, w, 0 xorlw d'32' btfsc STATUS, Z, 1 goto adrtoft rlcf Adr8, f, 0 ; 64 sectors per cluster rlcf Adr16, f, 0 rlcf Adr24, f, 0 rlcf Adr32, f, 0 movf sectclus, w, 0 xorlw d'64' btfsc STATUS, Z, 1 goto adrtoft rlcf Adr8, f, 0 ; 128 sectors per cluster rlcf Adr16, f, 0 rlcf Adr24, f, 0 rlcf Adr32, f, 0 movf sectclus, w, 0 xorlw d'128' btfsc STATUS, Z, 1 goto adrtoft ; if we branch here then there is an error adrtoft movf sdadrser8, w, 0 ; Add root directory offset addwf Adr8, f, 0 btfss STATUS, C, 1 goto adr_2 incf Adr16, f, 0 btfss STATUS, C, 1 goto adr_2 incf Adr24, f, 0 btfsc STATUS, C, 1 incf Adr32, f, 0 adr_2 movf sdadrser16, w, 0 addwf Adr16, f, 0 btfss STATUS, C, 1 goto adr_3 incf Adr24, f, 0 btfsc STATUS, C, 1 incf Adr32, f, 0 adr_3 movf sdadrser24, w, 0 addwf Adr24, f, 0 btfsc STATUS, C, 1 incf Adr32, f, 0 movf sdadrser32, w, 0 addwf Adr32, f, 0 return delent call SPIR decfsz temp1, f, 0 goto delent goto ReadDir_1 ;------------------------------------------------------------------------------- ;--------------------------------- Write File -------------------------------- ;------------------------------------------------------------------------------- WriteDir movf sdadrser8, w, 0 movwf Adr8, 0 movf sdadrser16, w, 0 movwf Adr16, 0 movf sdadrser24, w, 0 movwf Adr24, 0 movf sdadrser32, w, 0 movwf Adr32, 0 call ReadSD ; We are now at root directory movlw d'8' movwf temp3, 0 movlw d'128' movwf temp4, 0 ; total of 1024 root entries clrf Adr3, 0 clrf Adr2, 0 clrf Adr1, 0 call WrtMEM ; Move data from SD Card to ; memory chip wrtlbl_1 call chkentry decfsz temp4, f, 0 goto wrtlbl_1 movlw d'128' movwf temp4, 0 decfsz temp3, f, 0 goto wrtlbl_1 call Edcmd ; End read goto rewriteroot chkentry movlw d'31' movwf temp1, 0 call SPIR xorlw 0xE5 ; is entry valid ? btfsc STATUS, Z, 1 goto Invalent movf SPItemp, w, 0 call MEMSPI goto valentry valentry call SPIR ; Write valid entries call MEMSPI decfsz temp1, f, 0 goto valentry return Invalent call SPIR ; Discard invalid entries decfsz temp1, f, 0 goto Invalent return rewriteroot bsf MCS nop nop bcf MCS call memstatus bsf MCS clrf Adr3, 0 clrf Adr2, 0 clrf Adr1, 0 bcf MCS movlw 00000011b ; Read array call SPI movf Adr3, w, 0 call SPI movf Adr2, w, 0 call SPI movf Adr1, w, 0 call SPI call SPIF movlw d'1' ; number of sectors to write movwf temp4, 0 movf sdadrser8, w, 0 movwf Adr8, 0 movf sdadrser16, w, 0 movwf Adr16, 0 movf sdadrser24, w, 0 movwf Adr24, 0 movf sdadrser32, w, 0 movwf Adr32, 0 wrtroot call WriteSD ; Write memory chip to SD card decfsz temp4, f, 0 goto wrtroot incf Adr8, f, 0 return end