-; -*- 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.
;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 ;
; 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
; ----------------------------------;
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
; ----------------------------------;
; ----------------------------------;
-; 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 ;
; 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 ;
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 ;
; ----------------------------------;
; ----------------------------------;
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 ;
; 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
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
; ==================================;
; ==================================;
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 ;
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 ;
; ----------------------------------;
;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" ;
; ----------------------------------;
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
; ----------------------------------;
; 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
+; ----------------------------------;
; ======================================================================
; ----------------------------------;
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
; ----------------------------------;
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
; ----------------------------------;
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?
; 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 #XON ; use no registers
+ CALL #RXON ; use no registers
; ----------------------------------;
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
; ----------------------------------;
; ----------------------------------;
T2S_XOFF ; 27 cycles between XON and XOFF
; ----------------------------------;
- CALL #XOFF ;4 use no registers
+ CALL #RXOFF ;4 use no registers
JMP T2S_FillBufferLoop ;2 loop back to get 512th char
; ----------------------------------;
T2S_END ;
; ----------------------------------;
- CALL #XOFF ;4 use no registers
+ CALL #RXOFF ;4 use no registers
MOV Y,&BufferPtr ;3
CALL #CloseHandleT ;4
MOV @RSP+,IP ;2