-
Notifications
You must be signed in to change notification settings - Fork 2
/
SD-CARD.f
259 lines (229 loc) · 5.95 KB
/
SD-CARD.f
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
\ FROM JCW @ GETHUB EMBELLO/1608 FOR SD CARDS
\ NEEDS SPI_SETUP.F LOADED FIRST
\ NEEDS MS FROM TICK COMPARE(STRING)
HEX
: TUCK SWAP OVER ;
: NIP SWAP DROP ;
VARIABLE TEMP
: COMPARE ( $A $B Z - FLAG ) \ NOT OPIMAL JUST WORKS
0 TEMP !
1-
FOR
2DUP C@ SWAP C@ -
TEMP @ OR TEMP !
1 1 D+
NEXT
TEMP @ 0= ;
0E00E018 CONSTANT TICK
0FFFFFF TICK 4 - ! \ MAXIMUM COUNT
10005 TICK - 8 ! \ START TICK COUNTER
: MS ( N - ) \ 72MHz /8 = 9HHz
\ 1 MS = 9000d = 2328h
0 TICK !
2328 *
BEGIN
TICK @ OVER >
UNTIL DROP ;
: SD-SLOW ( - ) 38 DUP SPI1-CR1 MSK! ;
: SD-WAIT ( - ) BEGIN 0FF >SPI> ( DUP . ) 0FF = UNTIL ;
: SD-CMD ( CMD ARG - u )
SWAP \ CR MIILIS . ." CMD" DUP .
-SPI 2 US +SPI
0FF >SPI
40 OR >SPI
DUP 18 RSHIFT >SPI
DUP 10 RSHIFT >SPI
DUP 8 RSHIFT >SPI
>SPI
95 >SPI
BEGIN
0FF >SPI> DUP 80 AND
WHILE
DROP
REPEAT ;
: SD-INIT ( - )
SPI-INIT SD-SLOW 09 FOR 0FF >SPI NEXT
\ 0 TICKS !
BEGIN
0 0 SD-CMD \ CMD0 GO IDLE
01 =
UNTIL
BEGIN
10 MS ( NEEDS MS CODE )
37 0 SD-CMD DROP SD-WAIT
29 0 CD-CMD
0=
UNTIL
SPI-INIT \ BACK TO NORMAL SPEED
\ 3B 0 SD-CMD . SD-WAIT
\ 8 1AA SD-CMD . SD-WAIT
\ 10 200 SD-CMD . SD-WAIT
;
200 CREATE SD.BUF ALLOT
: SD-COPY ( F N - )
SWAP
BEGIN
( DUP . ) 0FE = NOT
WHILE \ WAIT FOR CHANGE AND THEN NOT 0FE
0FF >SPI>
REPEAT
1- DUP SD.BUF + SWAP
FOR
0FF >SPI>
OVER R@ - C!
NEXT DROP
0FF DUP >SPI >SPI ;
\ 0 1 2 3 4 5 6 7 8 9 A B C D E F CRC
\ 002E00325B5A83A9FFFFFF80168000916616 KINGSTON 2GB
\ 007F00325B5A83D3F6DBF819668000E7772B SANDISK 2GB
: SD-SIZE ( - N )
9 0 SD-CMD 10 SD-COPY
\ HTTPS://WWW.AVRFREAKS.NET/FORM/HOW-DETERMINE-MMC-CARD-SIZE
\ HTTPS://MEMBERS.SDCARD.ORG/DOWNLOADS/PLS/SIMPLIFIED_SPECS/ARCHIVE/PART1_301.PDF
\ TODO BYTES 6 AND 8 MAY BE REVERSED...
SD.BUF 6 + C@ 03 AND 0A LSHIFT
SD.BUF 7 + C@ 2 LSHIFT OR
SD.BUF 8 + C@ 6 RSHIFT OR ;
: SD-READ ( PAGE - ) \ READ ONE 512-BYTE PAGE FROM SDCARD
9 LSHIFT 11 SWAP SD-CMD 200 SD-COPY ;
: SD-WRITE ( PAGE - ) \ WRITE 512
9 LSHIFT 18 SWAP SD-CMD DROP
0FF >SPI 0FE >SPI
\ 200 0 DO SD.BUF I + C@ >SPI LOOP
1FF SD.BUFF + 1FF
FOR
DUP R@ - C@ >SPI
NEXT
0FF DUP >SPI >SPI SD-WAIT ;
\ FAT ACCESS
0 VARIABLE SD.FAT \ BLOCK # OF FIRST FAT
0 VARIABLE SD.SPC \ SECTORS PER CLUSTER (64)
0 VARIABLE SD.ROOT \ BLK# OF FIRST ROOT SECTOR
0 VARIABLE SD.#ENT \ NUMBER OF ROOT ENTRIES
0 VARIABLE SD.DATA \ BLK OFFSET OF CLUSTER #2
: SD-MOUNT ( - ) \ MOUNT A FAT16 VOLUME,EXTRACT THE KEY DISK INFO
SD-INIT \ IN INTERFACE CARD
0 SD-READ \ READ BLOCK #0
SD.BUF 1C6 + @ \ GET LOCATION OF BOOT SECTOR
DUP 1+ SD.FAT ! \ START SECTOR OF FAT AREA
DUP SD-READ \ READ BOOT RECORD
SD.BUF 0D + C@ \ SECTORS/CLUSTER
SD.SPC ! \ DEPENDS ON FORMATTED DISK SIZE
SD.BUF 0E + H@ \ RESERVED SECTOR
SD.BUF 10 + C@ \ NUMBER OF FAT COPIES
SD.BUF 16 + H@ \ SECTOR/FAT
* + + DUP SD.ROOT ! \ START SECTOR OF ROOT DIR
SD.BUF 11 + H@ \ MAX ROOT ENTRIES
DUP SD.#ENT ! \ SAVE FOR LATER
4 RSHIFT + SD.DATA ! ; \ START SECTOR OF DATA AREA
: SD.MOUNT. ( - ) \ MOUNT AND SHOW SOME BASIC CARD INFO
SD-MOUNT
CR ." LABEL: " SD.BUF 2B + 0B TYPE SPACE
." FORMAT: " SD.BUF 36 + 8 TYPE SPACE
." CAPACITY: " SD.BUF 20 + @ . ;
: DIRENT ( A - ) \ DISPLAY DIR ENTRY
DUP C@ 80 AND 0= OVER 2+ C@ AND
IF
CR DUP 0B TYPE SPACE
DUP 11 + C@ . SPACE
DUP 1A + H@ .
DUP 1C + @ .
THEN ;
VARIABLE CNT
: CNT++ CNT @ DUP 1+ CNT ! ;
: LS ( - ) \ DISPLAY ROOT DIR SKIPPING LFNs AND DELETED
SD.BUF 200 + \ DON'T LIKE THIS??
\ SD#ENT @ 0
\ DO
\ I 0F AND 0=
\ IF
\ SD.ROOT @ I 4 RSHIFT + SD-READ
\ 200 -
\ THEN
\ DIRENT 20 +
\ LOOP DROP ;
0 CNT !
SD#ENT @ 1-
FOR
CNT++ 0F AND 0=
IF
SD.ROOT@ CNT @ 1- 4 RSHIFT + SD-READ
200 -
THEN
DIRENT 20 +
NEXT DROP ;
\ : FAT-FIND ( ADDR - U ) \ FIND ENTRY BY NAME,
\ RETURN DATA CLUSTER, ELSE $FFFF
\ SD.BUF 200 + ( ADDR BEND )
\ SD.#ENT @ 0
\ DO
\ I 0F AND 0=
\ IF ( 10 DIR ENTRIES PER BUFF )
\ SD.ROOT @ i 4 RSHIFT + SD-READ ( READ NEXT )
\ 200 -
\ THEN
\ 2DUP 0B TUCK COMPARE
\ IF
\ NIP 1A + H@
\ UNLOOP
\ EXIT
\ THEN
\ 20 +
\ LOOP 2DROP 0FFFF ;
: FAT-FIND ( FileName$ - FAT/FFFF ) \ FFFF FAILS
\ ASSUME ROOT IS IN SD.BUF ( SD-MOUNT )
>R \ SAVE FILE NAME ADDRESS
0FFFF \ FAIL FLAG
SD#ENT @ \ ENTRIES
20 * \ LAST ENTRY OFFSET +1 ENTRY
0 \ FIRST ENTRY
BEGIN
2DUP - \ DONE WHEN ENTRY OFFSET = LAST OFFSET
WHILE
DUP 1E0 AND 0= \ 1E0 = ( 10 * 20 ) - 10
IF \ RELOAD EVERY 16 ENTRIES
SD.ROOT @ OVER ( 4 5 + ) 9 RSHIFT + SD-READ
THEN
DUP 1E0 AND SD.BUF + R@ 0B COMPARE ( FAIL LAST MATCH? )
IF
>R 2DROP \ DROP FAIL-FLAG AND LAST ENTRY+1
R> 1A + H@ \ FAT
R> DROP EXIT \ DROP FILE NAME
ELSE
20 + \ ENTRY SIZE
THEN
REPEAT
2DROP R> DROP ; \ FAIL FLAG ONLY
: FAT-NEXT ( FAT - FAT ) \ RETURN NEXT FAT CLUSTER, OR $FFFx AT END
\ TODO HARD-CODED FOR 64 SEC / 32 KB PER CLUSTER
DUP 8 RSHIFT SD.FAT @ + SD-READ
0FF AND 2* SD.BUF + H@ ;
: CHAIN. ( U - ) \ DISPLY THE CHAIN OF CLUSTERS
BEGIN
DUP .
DUP 0F OR 0FFFF <>
WHILE
FAT-NEXT
REPEAT DROP ;
\ 128 CLUSTERS IS 8 MB WHEN CLUSTER SIZE IS 64
4 CONSTANT NFILES
81 2* NFILES * CREATE FAT.MAPS ALLOT \ MAPS OF 128 CLUSTERS MAX
: FILE ( N - A ) \ CONVERT FILE 0,,3 TO A MAP ADDRESS INSIDE FAT.MAPS
81 2* * FAT.MAPS + ;
: FAT-CHAIN ( U N - ) \ STORE CLUSTERS FOR USE AS FILE MAP N
FILE
BEGIN
2DUP ! 2+ * FAT.MAPS + ;
: FAT-CHAIN ( U N - ) \ STORE CLUSTERS FOR USE AS FILE MAP N
FILE
BEGIN
2DUP ! 2+
OVER 0F OR 0FFFF <>
WHILE
SWAP FAT-NEXT SWAP
REPEAT 2DROP ;
: FAT-MAP ( N1 N2 - N ) \ MAP BLK N1 TO RAW BLK NUMBER USING FILE N2 MAP
FILE
OVER SD.SPC @ / 2* + H@
2 - SD.SPC @ * SWAP SD.SPC @ 1 - AND +
SD.DATA @ + ;