1 \ -*- coding: utf-8 -*-
3 ; ---------------------------------------------------------------
4 ; SD_TOOLS.f : BASIC TOOLS for SD Card : DIR FAT SECTOR CLUSTER
5 ; ---------------------------------------------------------------
7 \ to see kernel options, download FastForthSpecs.f
8 \ FastForth kernel options: MSP430ASSEMBLER, CONDCOMP, DOUBLE_INPUT, SD_CARD_LOADER
11 \ MSP_EXP430FR5739 MSP_EXP430FR5969 MSP_EXP430FR5994 MSP_EXP430FR6989
12 \ MSP_EXP430FR4133 CHIPSTICK_FR2433 MSP_EXP430FR2433 MSP_EXP430FR2355
15 \ R4 to R7 must be saved before use and restored after
16 \ scratch registers Y to S are free for use
17 \ under interrupt, IP is free for use
19 \ PUSHM order : PSP,TOS, IP, S, T, W, X, Y, rEXIT,rDOVAR,rDOCON, rDODOES, R3, SR,RSP, PC
20 \ PUSHM order : R15,R14,R13,R12,R11,R10, R9, R8, R7 , R6 , R5 , R4 , R3, R2, R1, R0
22 \ example : PUSHM #6,IP pushes IP,S,T,W,X,Y registers to return stack
24 \ POPM order : PC,RSP, SR, R3, rDODOES,rDOCON,rDOVAR,rEXIT, Y, X, W, T, S, IP,TOS,PSP
25 \ POPM order : R0, R1, R2, R3, R4 , R5 , R6 , R7 , R8, R9,R10,R11,R12,R13,R14,R15
27 \ example : POPM #6,IP pop Y,X,W,T,S,IP registers from return stack
30 \ FORTH conditionnals: unary{ 0= 0< 0> }, binary{ = < > U< }
32 \ ASSEMBLER conditionnal usage with IF UNTIL WHILE S< S>= U< U>= 0= 0<> 0>=
33 \ ASSEMBLER conditionnal usage with ?JMP ?GOTO S< S>= U< U>= 0= 0<> 0<
35 [DEFINED] {SD_TOOLS} [IF] {SD_TOOLS} [THEN]
37 [UNDEFINED] {SD_TOOLS} [IF]
41 [UNDEFINED] MARKER [IF]
42 \ https://forth-standard.org/standard/core/MARKER
44 \ ( "<spaces>name" -- )
45 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
46 \ with the execution semantics defined below.
48 \ name Execution: ( -- )
49 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
50 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
51 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
52 \ not necessarily provided. No other contextual information such as numeric base is affected
57 MOV &LASTVOC,0(W) \ [BODY] = LASTVOC
59 MOV Y,2(W) \ 3 [BODY+2] = LFA = DP to be restored
60 ADD #4,&DP \ 3 add 2 cells
65 MOV @TOS+,&INIVOC \ set VOC_LINK value for RST_STATE
66 MOV @TOS,&INIDP \ set DP value for RST_STATE
68 MOV #RST_STATE,PC \ execute RST_STATE, PWR_STATE then STATE_DOES
75 \ https://forth-standard.org/standard/core/Plus
76 \ + n1/u1 n2/u2 -- n3/u3 add n1+n2
83 [UNDEFINED] MAX [IF] \ MAX and MIN are defined in {UTILITY}
85 CODE MAX \ n1 n2 -- n3 signed maximum
92 CODE MIN \ n1 n2 -- n3 signed minimum
102 \ https://forth-standard.org/standard/core/CFetch
103 \ C@ c-addr -- char fetch char from memory
111 \ https://forth-standard.org/standard/core/Store
112 \ ! x a-addr -- store cell in memory
120 [UNDEFINED] SPACE [IF]
121 \ https://forth-standard.org/standard/core/SPACE
122 \ SPACE -- output a space
127 [UNDEFINED] SPACES [IF]
128 \ https://forth-standard.org/standard/core/SPACES
129 \ SPACES n -- output n spaces
143 MOV @PSP+,TOS \ -- drop n
148 [UNDEFINED] SWAP [IF]
149 \ https://forth-standard.org/standard/core/SWAP
150 \ SWAP x1 x2 -- x2 x1 swap top two items
159 [UNDEFINED] OVER [IF]
160 \ https://forth-standard.org/standard/core/OVER
161 \ OVER x1 x2 -- x1 x2 x1
163 MOV TOS,-2(PSP) \ 3 -- x1 (x2) x2
164 MOV @PSP,TOS \ 2 -- x1 (x2) x1
165 SUB #2,PSP \ 1 -- x1 x2 x1
171 \ https://forth-standard.org/standard/core/toR
172 \ >R x -- R: -- x push to return stack
181 \ https://forth-standard.org/standard/core/Rfrom
182 \ R> -- x R: x -- pop from return stack ; CALL #RFROM performs DOVAR
189 \ https://forth-standard.org/standard/core/Minus
190 \ - n1/u1 n2/u2 -- n3/u3 n3 = n1-n2
192 SUB @PSP+,TOS \ 2 -- n2-n1 ( = -n3)
194 ADD #1,TOS \ 1 -- n3 = -(n2-n1) = n1-n2
199 [UNDEFINED] U.R [IF] \ defined in {UTILITY}
200 : U.R \ u n -- display u unsigned in n width (n >= 2)
202 R> OVER - 0 MAX SPACES TYPE
207 \ https://forth-standard.org/standard/core/DO
208 \ DO -- DOadr L: -- 0
212 ADD #2,&DP \ make room to compile xdo
213 MOV &DP,TOS \ -- HERE+2
214 MOV #XDO,-2(TOS) \ compile xdo
215 ADD #2,&LEAVEPTR \ -- HERE+2 LEAVEPTR+2
217 MOV #0,0(W) \ -- HERE+2 L-- 0
222 [UNDEFINED] LOOP [IF]
223 \ https://forth-standard.org/standard/core/LOOP
224 \ LOOP DOadr -- L-- an an-1 .. a1 0
225 CODE LOOP \ immediate
227 BW1 ADD #4,&DP \ make room to compile two words
229 MOV X,-4(W) \ xloop --> HERE
230 MOV TOS,-2(W) \ DOadr --> HERE+2
231 BEGIN \ resolve all "leave" adr
232 MOV &LEAVEPTR,TOS \ -- Adr of top LeaveStack cell
233 SUB #2,&LEAVEPTR \ --
234 MOV @TOS,TOS \ -- first LeaveStack value
235 CMP #0,TOS \ -- = value left by DO ?
237 MOV W,0(TOS) \ move adr after loop as UNLOOP adr
244 [UNDEFINED] +LOOP [IF]
245 \ https://forth-standard.org/standard/core/PlusLOOP
246 \ +LOOP adrs -- L-- an an-1 .. a1 0
247 CODE +LOOP \ immediate
254 \ https://forth-standard.org/standard/core/I
255 \ I -- n R: sys1 sys2 -- sys1 sys2
256 \ get the innermost loop index
258 SUB #2,PSP \ 1 make room in TOS
260 MOV @RSP,TOS \ 2 index = loopctr - fudge
266 [UNDEFINED] DUMP [IF] \ defined in {UTILITY}
267 \ https://forth-standard.org/standard/tools/DUMP
268 CODE DUMP \ adr n -- dump memory
270 PUSH &BASEADR \ save current base
271 MOV #$10,&BASEADR \ HEX base
272 ADD @PSP,TOS \ -- ORG END
275 DO CR \ generate line
276 I 4 U.R SPACE \ generate address
283 I $10 + I \ display 16 chars
284 DO I C@ $7E MIN $20 MAX EMIT LOOP
286 R> BASEADR ! \ restore current base
290 \ display content of a sector
291 \ ----------------------------------\
292 CODE SECTOR \ sector. -- don't forget to add decimal point to your sector number
293 \ ----------------------------------\
294 BW1 MOV TOS,X \ X = SectorH
295 MOV @PSP,W \ W = sectorL
296 CALL &ReadSectorWX \ W = SectorLO X = SectorHI
298 <# #S #> TYPE SPACE \ ud -- display the double number
299 SD_BUF $200 DUMP CR ; \ then dump the sector
300 \ ----------------------------------\
302 \ display first sector of a Cluster
303 \ ----------------------------------\
304 CODE CLUSTER \ cluster. -- don't forget to add decimal point to your cluster number
305 \ ----------------------------------\
306 BW2 MOV.B &SecPerClus,W \ SecPerClus(54321) = multiplicator
307 MOV @PSP,X \ X = ClusterL
310 ADD X,X \ (RLA) shift one left MULTIPLICANDlo16
311 ADDC TOS,TOS \ (RLC) shift one left MULTIPLICANDhi8
312 FW1 RRA W \ shift one right multiplicator
313 U>= UNTIL \ carry set
314 ADD &OrgClusters,X \ add OrgClusters = sector of virtual cluster 0 (word size)
316 ADDC #0,TOS \ don't forget carry
317 GOTO BW1 \ jump to SECTOR
319 \ ----------------------------------\
321 \ ----------------------------------\
322 CODE FAT \ Display CurFATsector
323 \ ----------------------------------\
326 MOV &OrgFAT1,0(PSP) \
327 MOV #0,TOS \ FATsectorHI = 0
328 GOTO BW1 \ jump to SECTOR
330 \ ----------------------------------\
332 \ ----------------------------------\
333 CODE DIR \ Display CurrentDir first sector
334 \ ----------------------------------\
336 MOV TOS,2(PSP) \ save TOS
337 MOV &DIRclusterL,0(PSP) \
338 MOV &DIRclusterH,TOS \
340 0<> ?GOTO BW2 \ jump to CLUSTER
341 CMP #1,0(PSP) \ cluster 1 ?
342 0<> ?GOTO BW2 \ jump to CLUSTER
343 MOV &OrgRootDir,0(PSP) \ if yes, special case of FAT16 OrgRootDir
344 GOTO BW1 \ jump to SECTOR
346 \ ----------------------------------\