OSDN Git Service

added the line number when an error occurs
[fast-forth/master.git] / forthMSP430FR_SD_RW.asm
index d942826..0773486 100644 (file)
@@ -1,4 +1,4 @@
-; -*- coding: utf-8 -*-
+ ; -*- coding: utf-8 -*-
 ; DTCforthMSP430FR5xxxSD_RW.asm
 
 ; and only for FR5xxx and FR6xxx with RTC_B or RTC_C hardware if you want write file with date and time.
@@ -43,11 +43,11 @@ OPEN_READ                           ;
 
 ;Z READ            -- f
 ; sequentially read a file opened by READ".
-; sectors are loaded in BUFFER and BufferLen leave the count of loaded bytes.
+; sectors are loaded in SD_BUF and BufferLen leave the count of loaded bytes.
 ; when the last sector of file is loaded in buffer, the handle is automatically closed and flag is true (<>0).
 
 ; ----------------------------------;
-    FORTHWORD "READ"                ; -- fl     closed ?
+    FORTHWORD "READ"                ; -- fl     closed flag
 ; ----------------------------------;
 READ
     SUB     #2,PSP                  ;
@@ -69,7 +69,7 @@ READ
 
 ; input : CurFATsector
 ; use SWX registers
-; output: W = new FATsector, BUFFER = [new FATsector], NewCluster
+; output: W = new FATsector, SD_BUF = [new FATsector], NewCluster
 ;         SectorL is unchanged, FATS are not updated.
 ;         S = 2 --> Disk FULL error
 ; ----------------------------------;
@@ -93,27 +93,27 @@ SearchFreeClustInBUF                ; <== SearchNextCluster
     CMP     #2,Y                    ; FAT16 Cluster size ?
     JZ      ClusterLowWordTest      ; yes
 ClusterHighWordTest                 ;
-    CMP     #0,BUFFER+2(X)          ; cluster address hi word = 0 ?
+    CMP     #0,SD_BUF+2(X)          ; cluster address hi word = 0 ?
     JNZ     SearchNextNewCluster    ;
 ClusterLowWordTest                  ;
-    CMP     #0,BUFFER(X)            ; Cluster address lo word = 0 ?
+    CMP     #0,SD_BUF(X)            ; Cluster address lo word = 0 ?
     JZ      GNC_FreeClusterFound    ; 
 SearchNextNewCluster                ;
-    ADD     Y,X                     ; increment BUFFER offset by size of Cluster address
+    ADD     Y,X                     ; increment SD_BUF offset by size of Cluster address
     CMP     #BytsPerSec,X           ;
     JNE     SearchFreeClustInBUF    ; loopback while X < BytsPerSec
 IncrementFATsector                  ;
     ADD     #1,0(RSP)               ; increment FATsector
     JMP     LoadFATsectorInBUF      ; loopback
 ; ----------------------------------;
-GNC_FreeClusterFound                ; Y =  cluster number low word in BUFFER = FATsector
+GNC_FreeClusterFound                ; Y =  cluster number low word in SD_BUF = FATsector
 ; ----------------------------------;
     MOV     #0,S                    ; clear error
     MOV.B   @RSP,W                  ; W = 0:FATsectorLo
-    MOV     #-1,BUFFER(X)           ; mark NewCluster low word as end cluster (0xFFFF) in BUFFER
+    MOV     #-1,SD_BUF(X)           ; mark NewCluster low word as end cluster (0xFFFF) in SD_BUF
     CMP     #2,Y                    ; Y = FAT16 size of Cluster number ?
     JZ      FAT16EntryToClusterNum  ; yes
-    MOV     #0FFFh,BUFFER+2(X)      ; no: mark NewCluster high word as end cluster (0x0FFF) in BUFFER
+    MOV     #0FFFh,SD_BUF+2(X)      ; no: mark NewCluster high word as end cluster (0x0FFF) in SD_BUF
 ; ----------------------------------;
 FAT32EntryToClusterNum              ; convert FAT32 cluster address to cluster number
 ; ----------------------------------;
@@ -142,8 +142,8 @@ SearchNewClusterEnd                 ;
 ; ----------------------------------;
 
 
-; update FATs with BUFFER content.
-; input : FATsector, FAToffset, BUFFER = [FATsector]
+; update FATs with SD_BUF content.
+; input : FATsector, FAToffset, SD_BUF = [FATsector]
 ; use : SWX registers
 ; ----------------------------------; else update FATsector of the old cluster
 UpdateFATsSectorW                   ;
@@ -202,11 +202,8 @@ SD_RW_RET                           ;
 
 
 ; when create filename, forbidden chars are skipped
-ForbiddenChars ; 15 forbidden chars + dot char table
-;          "  *  +  ,  /  :  ;  <  =  >  ?  [  \  ]  |  .
-    .byte 34,42,43,44,47,58,59,60,61,62,63,91,92,93,124,46
-
-
+ForbiddenChars ; 15 forbidden chars table + dot char
+    .byte '"','*','+',',','/',':',';','<','=','>','?','[','\\',']','|','.'
 
 ; ----------------------------------;
 OPWC_SkipDot                        ;
@@ -222,9 +219,11 @@ OPWC_SkipDot                        ;
 FillDIRentryName                    ;SWXY use
 ; ----------------------------------;
     MOV.B   @T+,W                   ; W = char of pathname
-    MOV.B   W,BUFFER(Y)             ;     to DIRentry
-    CMP     #0,W                    ; end of stringZ ?
-    JZ      OPWC_CompleteWithSpaces ;
+    MOV.B   W,SD_BUF(Y)             ;     to DIRentry
+;    CMP     #0,W                    ; end of stringZ ?
+;    JZ      OPWC_CompleteWithSpaces ;
+    CMP     T,&EndOfPath            ; EOS < PTR ?
+    JLO     OPWC_CompleteWithSpaces ; yes
 ; ----------------------------------;
 SkipForbiddenChars                  ;
 ; ----------------------------------;
@@ -254,7 +253,7 @@ OPWC_CompleteWithSpaces             ; 0 to n spaces !
 ; ----------------------------------;
 OPWC_CompleteWithSpaceloop          ;
 ; ----------------------------------;
-    MOV.B   #32,BUFFER(Y)           ; remplace dot by char space
+    MOV.B   #' ',SD_BUF(Y)          ; remplace dot by char space
     ADD     #1,Y                    ; increment DIRentry ptr in buffer 
     SUB     #1,X                    ; dec countdown of chars space
     JNZ OPWC_CompleteWithSpaceloop  ;
@@ -336,22 +335,23 @@ OPEN_WRITE_CREATE                   ;
 ; 4 init DIRentryAttributes         ;
 ; ----------------------------------;
 OPWC_SetEntryAttribute              ; (cluster=DIRcluster!)
-    MOV.B   #20h,BUFFER+11(Y)       ; file attribute = file
+    MOV.B   #20h,SD_BUF+11(Y)       ; file attribute = file
     CALL    #GetYMDHMSforDIR        ;WX  X=DATE,  W=TIME
-    MOV     #0,BUFFER+12(Y)         ; nt reserved = 0 and centiseconds are 0
-    MOV     W,BUFFER+14(Y)          ; time of creation
-    MOV     X,BUFFER+16(Y)          ; date of creation      20/08/2001
-    MOV     X,BUFFER+18(Y)          ; date of access        20/08/2001
-    MOV     &ClusterH,BUFFER+20(Y)  ; as first Cluster Hi 
-    MOV     &ClusterL,BUFFER+26(Y)  ; as first cluster LO   
-    MOV     #0,BUFFER+28(Y)         ; file lenghtLO  = 0 
-    MOV     #0,BUFFER+30(Y)         ; file lenghtHI  = 0 
+    MOV     #0,SD_BUF+12(Y)         ; nt reserved = 0 and centiseconds are 0
+    MOV     W,SD_BUF+14(Y)          ; time of creation
+    MOV     X,SD_BUF+16(Y)          ; date of creation      20/08/2001
+    MOV     X,SD_BUF+18(Y)          ; date of access        20/08/2001
+    MOV     &ClusterH,SD_BUF+20(Y)  ; as first Cluster Hi 
+    MOV     &ClusterL,SD_BUF+26(Y)  ; as first cluster LO   
+    MOV     #0,SD_BUF+28(Y)         ; file lenghtLO  = 0 
+    MOV     #0,SD_BUF+30(Y)         ; file lenghtHI  = 0 
 ; ----------------------------------;
 ; 5 create DIRentryName             ;
 ; ----------------------------------;
     MOV     #1,S                    ; preset pathname error
     MOV     &Pathname,T             ; here, pathname is "xxxxxxxx.yyy" format
-    CMP.B   #0,0(T)                 ; forbidden null string
+;    CMP.B   #0,0(T)                 ; forbidden null string
+    CMP     T,&EndOfPath            ;
     JZ      OPWC_InvalidPathname    ; write error 1
     CMP.B   #'.',0(T)               ; forbidden "." in first
     JZ      OPWC_InvalidPathname    ; write error 1
@@ -385,18 +385,18 @@ OPWW_UpdateDirectory                ; <== CloseHandleT
     CALL    #readSectorWX           ;SWX buffer = DIRsector
     CALL    #GetYMDHMSforDIR        ; X=DATE,  W=TIME
     MOV     HDLW_DIRofst(T),Y       ; Y = DirEntryOffset
-    MOV     X,BUFFER+18(Y)          ; access date
-    MOV     W,BUFFER+22(Y)          ; modified time
-    MOV     X,BUFFER+24(Y)          ; modified date
+    MOV     X,SD_BUF+18(Y)          ; access date
+    MOV     W,SD_BUF+22(Y)          ; modified time
+    MOV     X,SD_BUF+24(Y)          ; modified date
 OPWW_UpdateEntryFileSize            ;
-    MOV HDLL_CurSize(T),BUFFER+28(Y); save new filesize
-    MOV HDLH_CurSize(T),BUFFER+30(Y);
+    MOV HDLL_CurSize(T),SD_BUF+28(Y); save new filesize
+    MOV HDLH_CurSize(T),SD_BUF+30(Y);
     MOV     HDLL_DIRsect(T),W       ; 
     MOV     HDLH_DIRsect(T),X       ;
     MOV     #WriteSectorWX,PC       ;SWX then RET
 ; ----------------------------------;
 
-; this subroutine is called by Write_File and CloseHandleT
+; this subroutine is called by Write_File (bufferPtr=512) and CloseHandleT (0 =< BufferPtr =< 512)
 ; ==================================; 
 WriteBuffer                         ;SWXY input: T = CurrentHDL
 ; ==================================; 
@@ -420,7 +420,7 @@ Write_File                          ; <== WRITE, SD_EMIT, TERM2SD"
 ; ==================================;
     MOV     #BytsPerSec,&BufferPtr  ; write always all the buffer
     MOV     &CurrentHdl,T           ;
-    CALL    #WriteBuffer            ; write BUFFER and update Handle informations only for DIRentry update 
+    CALL    #WriteBuffer            ; write SD_BUF and update Handle informations only for DIRentry update 
     MOV     #0,&BufferPtr           ; reset buffer pointer
 ; ----------------------------------;
 PostIncrementSector                 ;
@@ -445,10 +445,10 @@ UpdateNewClusterFATs                ;
 LinkClusters                        ;
     MOV     @RSP+,W                 ; W = current FATsector
     MOV     @RSP+,Y                 ; pop current FAToffset
-    MOV     &NewClusterL,BUFFER(Y)  ; store new cluster to current cluster address in current FATsector buffer
+    MOV     &NewClusterL,SD_BUF(Y)  ; store new cluster to current cluster address in current FATsector buffer
     CMP     #1,&FATtype             ; FAT16?
     JZ UpdatePreviousClusterFATs    ; yes
-    MOV     &NewClusterH,BUFFER+2(Y);
+    MOV     &NewClusterH,SD_BUF+2(Y);
 UpdatePreviousClusterFATs           ;
     CALL    #UpdateFATsSectorW      ;SWX update FATS with current FATsector buffer
 UpdateHandleCurCluster              ;
@@ -461,7 +461,7 @@ Write_File_End
 ; ----------------------------------;
 
 ;Z WRITE            -- 
-; sequentially write the BUFFER in a file opened by WRITE"
+; sequentially write the entire SD_BUF in a file opened by WRITE"
 ; ----------------------------------;
     FORTHWORD "WRITE"               ;
 ; ----------------------------------;
@@ -478,12 +478,12 @@ SD_EMIT                             ;
     JLO     SD_EmitNext             ; 2
     CALL    #Write_File             ;   BufferPtr = 0
 SD_EmitNext                         ;
-    MOV     &BufferPtr,Y            ; Y 
-    MOV.B   TOS,BUFFER(Y)           ; 3
+    MOV     &BufferPtr,Y            ; 3 
+    MOV.B   TOS,SD_BUF(Y)           ; 3
     ADD     #1,&BufferPtr           ; 4
     MOV     @PSP+,TOS               ; 2
     mNEXT                           ; 4
-; ----------------------------------; 19~ for SD_EMIT, 22~ for EMIT
+; ----------------------------------; 22~ for SD_EMIT, 22~ for EMIT
 
 
 
@@ -506,43 +506,56 @@ OPEN_WRITE_APPEND                   ;
 ; ----------------------------------;
 ; 2.1- Compute Sectors count        ; Sectors = HDLL_CurSize/512
 ; ----------------------------------;
-    MOV.B   HDLL_CurSize+1(T),Y     ; Y = 0:CurSizeLoHi
-    MOV.B   HDLH_CurSize(T),S       ; S = 0:CurSizeHiLo 
-    SWPB    S                       ; S = CurSizeHiLo:0 
-    ADD     Y,S                     ; S = CurSizeHiLo:CurSizeLoHi
-    MOV.B   HDLH_CurSize+1(T),W     ; W:S = CurSize / 256
-    RRA     W                       ; W = Sectors number_High
-    RRC     S                       ; S = Sectors number_Low
-; ----------------------------------;
-; 2.2- Compute Buffer offset        ; tested with 4100 bytes and SecPerClus=8
-; ----------------------------------;
-    MOV     HDLL_CurSize(T),Y       ; Y = 1004
-    BIC     #01FFh,HDLL_CurSize(T)  ; substract 4 from HDLL_CurSize
-    AND     #01FFh,Y                ; Y = 4
-    MOV     Y,&BufferPtr            ; init Buffer Pointer with 4
-; ----------------------------------;
-ComputeClustersCount                ; with  W:S / T ==> quotient = Y:X, remainder = W
-; ----------------------------------;
-    MOV.B &SecPerClus,T             ;3 T = DIVISOR = SecPerClus
-    CALL #UDIVQ32                   ; unsigned division 32/16 ==> Q32,R16 i.e. W:S/T ==> Y:X,W     use S,T,W,X,Y
-    MOV &CurrentHDL,T               ;
-; ----------------------------------;
-; 2.3- Compute Cluster offset       ;
-; ----------------------------------;
-    MOV.B W,HDLB_ClustOfst(T)       ;3  update handle with W = R16 (remainder) = sectors offset in cluster
-; ----------------------------------;
-; 2.4- Compute last Cluster         ; X = Q32lo = Clusters numberLO, Y = Q32hi = Clusters numberHI 
+    MOV.B   HDLL_CurSize+1(T),Y     ;Y = 0:CurSizeLOHi
+    MOV.B   HDLH_CurSize(T),X       ;X = 0:CurSizeHILo 
+    SWPB    X                       ;X = CurSizeHIlo:0 
+    ADD     Y,X                     ;X = CurSizeHIlo:CurSizeLOhi
+    MOV.B   HDLH_CurSize+1(T),Y     ;Y:X = CurSize / 256
+;    RRA     Y                       ;Y = Sectors number_High
+;    RRC     X                       ;X = Sectors number_Low
+; ----------------------------------;
+; 2.2 Compute Clusters Count        ;
+; ----------------------------------;
+    MOV.B &SecPerClus,T             ;3 T = DIVISOR = SecPerClus = 0:SPClo
+DIVSECPERSPC                        ;
+    MOV #0,W                        ;1 W = 0:REMlo = 0
+    MOV #8,S                        ;1 S = CNT
+;    RRA T                           ;1 0>0:SPClo>C   preshift one right DIVISOR
+DIVSECPERSPC1                       ;
+    RRA Y                           ;1 0>0:SEC_HI>C
+    RRC X                           ;1 C>SEC_LO>C
+    RRC.B W                         ;1 C>REMlo>C
+    SUB #1,S                        ;1 CNT-1
+    RRA T                           ;1 0>SPChi:SPClo>C
+    JNC DIVSECPERSPC1               ;2 7~ loopback if carry clear
+DIVSECPERSPC2                       ;
+    RRA W                           ;1 0>0:REMlo>C
+    SUB #1,S                        ;1 CNT-1
+;   JNZ DIVSECPERSPC2               ;2 4~ loopback     Wlo = OFFSET, X = CLU_LO, Y = CLU_HI
+    JGE DIVSECPERSPC2               ;2 4~ loopback     Wlo = OFFSET, X = CLU_LO, Y = CLU_HI
+; ----------------------------------;
+    MOV &CurrentHDL,T               ;3  reload Handle ptr  
+; ----------------------------------;
+; 2.3- Compute last Cluster         ; X = Clusters numberLO, Y = Clusters numberHI 
 ; ----------------------------------;
     ADD  HDLL_FirstClus(T),X        ;
     ADDC HDLH_FirstClus(T),Y        ;
     MOV X,HDLL_CurClust(T)          ;  update handle
     MOV Y,HDLH_CurClust(T)          ;
 ; ----------------------------------;
-; 3- load last sector in BUFFER     ;
+; 2.4- Compute Sectors offset       ;
 ; ----------------------------------;
+    MOV.B W,HDLB_ClustOfst(T)       ;3  update handle with W = REMlo = sectors offset in last cluster
+; ----------------------------------;
+; 3- load last sector in SD_BUF     ;
+; ----------------------------------;
+    MOV     HDLL_CurSize(T),W       ; example : W = 1013
+    BIC     #01FFh,HDLL_CurSize(T)  ; substract 13 from HDLL_CurSize, because loaded in buffer
+    AND     #01FFh,W                ; W = 13
+    MOV     W,&BufferPtr            ; init Buffer Pointer with 13
     CALL    #LoadHDLcurrentSector   ;SWX
-    mNEXT                           ; --
-; ----------------------------------; BufferPtr leaves first free byte offset
+    mNEXT                           ; BufferPtr = first free byte offset
+; ----------------------------------;
 
 
 ; ======================================================================
@@ -573,7 +586,7 @@ SelectFreeEntry                     ; nothing to do: S = 0 ready for free entry!
 ; ----------------------------------;
     CMP     #BytsPerSec-32,Y        ; Entry >= last entry in DIRsector ?
     JHS     SelectHideEntry         ; yes:  next DIR entry is out of sector
-    CMP.B   #0,BUFFER+32(Y)         ; no:   next DIR entry in DIRsector is free?
+    CMP.B   #0,SD_BUF+32(Y)         ; no:   next DIR entry in DIRsector is free?
     JZ      WriteDelEntry           ;       yes
 ; ----------------------------------;
 SelectHideEntry                     ;       no
@@ -582,7 +595,7 @@ SelectHideEntry                     ;       no
 ; ----------------------------------;
 WriteDelEntry
 ; ----------------------------------;
-    MOV.B   S,BUFFER(Y)             ; 
+    MOV.B   S,SD_BUF(Y)             ; 
     CALL    #WriteSector            ;SWX  write SectorHL=DIRsector
 ; ----------------------------------;
 ; 3- free all file clusters         ; Cluster = FirstCluster
@@ -598,14 +611,14 @@ LoadFAT1sector
 ; ----------------------------------;
 GetAndFreeClusterLo                 ;
 ; ----------------------------------;
-    MOV     BUFFER(Y),W             ; get [clusterLO]
-    MOV     #0,BUFFER(Y)            ; free CLusterLO
+    MOV     SD_BUF(Y),W             ; get [clusterLO]
+    MOV     #0,SD_BUF(Y)            ; free CLusterLO
 ClusterTestSelect                   ;
     CMP     #1,&FATtype             ; FAT16 ?
     JZ      ClusterLoTest           ; yes
 GetAndFreeClusterHi                 ;
-    MOV     BUFFER+2(Y),X           ; get [clusterHI]
-    MOV     #0,BUFFER+2(Y)          ; free CLusterHI
+    MOV     SD_BUF+2(Y),X           ; get [clusterHI]
+    MOV     #0,SD_BUF+2(Y)          ; free CLusterHI
 ClusterHiTest
     AND     #00FFFh,X               ; select 12 bits significant
     CMP     #00FFFh,X               ; [ClusterHI] was = 0FFFh?
@@ -646,21 +659,18 @@ OPND_End                            ;
 ; then when XON is sent below, TERATERM sends "file.ext" by slices of 512 bytes,
 ; until it sends char ETX that closes the file on SD_CARD.
 
+
     FORTHWORD "TERM2SD\34"
     mDOCOL
-    .word   DELDQ                   ;   DEL file if already exist
-    .word   HERE                    ;
+    .word   DELDQ                   ;                   DEL filepath if already exist
+    .word   lit,2                   ; -- open_type
+    .word   HERE,COUNT              ; -- open_type addr cnt
+    .word   PARENOPEN               ;                   reopen same filepath but as write
     FORTHtoASM                      ;
-    ADD     #2,RSP                  ; pop IP of OPEN
-    SUB     #2,PSP                  ;
-    MOV     #2,0(PSP)               ; -- open_type HERE     open_type = open as write
-    MOV     #TERM2SD,IP             ;                       IP = ParenOpen return address
-    MOV     #PARENOPEN,PC           ; open_type HERE --     open as write the file whose HERE is the c-addr of pathname
-TERM2SD                             ;
-    FORTHtoASM                      ; T = CurrentHdl
+    MOV     @RSP+,IP                ;
     BIC     #UCRXIFG,&TERMIFG       ;   clean up RX buffer  
 ; ----------------------------------;
-T2S_GetSliceLoop                    ;   tranfert by slices of 512 bytes terminal input to file on SD_CARD via BUFFER 
+T2S_GetSliceLoop                    ;   tranfert by slices of 512 bytes terminal input to file on SD_CARD via SD_BUF 
 ; ----------------------------------;
     MOV     #0,Y                    ;1  reset Y = BufferPtr
     CALL    #RXON                   ;   use no registers
@@ -670,13 +680,13 @@ T2S_FillBufferLoop                  ;
     BIT     #UCRXIFG,&TERMIFG       ;3 new char in TERMRXBUF ?
     JZ      T2S_FillBufferLoop      ;2
     MOV.B   &TERMRXBUF,X            ;3
-    CMP.B   #4,X                    ;1 ETX sent by TERATERM ?
+    CMP.B   #4,X                    ;1 EOT sent by TERATERM ?
     JZ      T2S_END                 ;2 yes
-    MOV.B   X,BUFFER(Y)             ;3
+    MOV.B   X,SD_BUF(Y)             ;3
     ADD     #1,Y                    ;1
     CMP     #BytsPerSec-1,Y         ;2
-    JZ      T2S_XOFF                ;2 Y=511    send XOFF after RX 511th char
     JLO     T2S_FillBufferLoop      ;2 Y<511    21 cycles char loop
+    JZ      T2S_XOFF                ;2 Y=511    send XOFF after RX 511th char
 ; ----------------------------------;
 T2S_WriteFile                       ;2 Y>511
 ; ----------------------------------;