file.c


1
/*
2
 *   Doku, siehe http://www.mikrocontroller.net/articles/AVR_FAT32
3
 *  Neuste Version: http://www.mikrocontroller.net/svnbrowser/avr-fat32/
4
 *  Autor: Daniel R.
5
 */
6
7
#include <string.h>  
8
#include <stdlib.h>
9
10
#include "config.h"
11
#include "mmc.h"
12
#include "fat.h"
13
#include "file.h"
14
15
#if (MMC_MULTI_BLOCK==TRUE && MMC_OVER_WRITE==FALSE)
16
  unsigned char  multiblock_flag;
17
#endif
18
19
20
//*******************************************************************************************************************************
21
// funktionsprototypen die nur in dieser datei benutzt werden !
22
#if (MMC_LS==TRUE)
23
  static void lsRowsOfClust (fptr uputs_ptr, unsigned long int start_sec);  // zeigt reihen eines clusters an, ab start_sec, muss zeiger auf eine ausgabe funktion überbeben bekommen
24
#endif
25
//*******************************************************************************************************************************
26
27
28
#if (MMC_FILE_EXSISTS==TRUE)
29
// *******************************************************************************************************************************
30
// prueft ob es die datei im aktuellen verzeichnis gibt.
31
// ffopen wuerde die datei direkt anlegen, falls es sie noch nicht gibt!
32
// *******************************************************************************************************************************
33
unsigned char ffileExsists ( unsigned char name[]){
34
  return fat_loadFileDataFromDir(name);
35
}
36
#endif
37
38
//*******************************************************************************************************************************
39
// 2 moeglichkeiten beim oeffnen, datei existiert(return MMC_FILE_EXISTS) oder muss angelegt werden(return MMC_FILE_NEW)
40
// zuerst wird geprueft ob es die datei im verzeichniss gibt. danach wird entschieden, ob die datei geoeffnet wird oder angelegt.
41
// -beim oeffnen werden die bekannten cluster gesucht maximal MAX_CLUSTERS_IN_ROW in reihe. dann wird der 1. sektor der datei auf
42
// den puffer fat.sector geladen. jetzt kann man ffread lesen...
43
// -beim anlegen werden freie cluster gesucht, maximal MAX_CLUSTERS_IN_ROW in reihe. dann wird das struct file gefuellt.
44
// danach wird der dateieintrag gemacht(auf karte). dort wird auch geprueft ob genügend platz im aktuellen verzeichniss existiert.
45
// moeglicherweise wird der 1. cluster der datei nochmal geaendert. jetzt ist der erste frei sektor bekannt und es kann geschrieben werden.
46
//*******************************************************************************************************************************
47
unsigned char ffopen( unsigned char name[]){
48
49
  unsigned char file_flag = fat_loadFileDataFromDir(name);  //pruefung ob datei vorhanden. wenn vorhanden, laden der daten auf das file struct.
50
51
  if( file_flag==TRUE ){                    /** datei existiert, anlegen nicht noetig! **/
52
    fat_getFatChainClustersInRow( file.firstCluster );    // verkettete cluster aus der fat-chain suchen.
53
    file.name = name;
54
55
    #if (MMC_MULTI_BLOCK==TRUE && MMC_OVER_WRITE==FALSE)
56
      fat.currentSectorNr = fat.startSectors;
57
      multiblock_flag = TRUE;
58
      mmc_multi_block_start_read (fat.startSectors);
59
      mmc_multi_block_read_sector (fat.sector);
60
    #else
61
      fat_loadSector( fat.startSectors );    // laed die ersten 512 bytes der datei auf puffer:sector.
62
    #endif
63
64
    return MMC_FILE_EXISTS;
65
  }
66
67
  #if (MMC_WRITE==TRUE)                    // anlegen ist schreiben !
68
  else{                            /** datei existiert nicht, also anlegen !  (nur wenn schreiben option an ist)**/
69
    file.name = name;                    // pointer "sichern" ;)
70
    fat_makeFileEntry(name,0x20);              // DATEI ANLEGEN auf karte
71
    #if (MMC_MULTI_BLOCK==TRUE && MMC_OVER_WRITE==FALSE)
72
      multiblock_flag = FALSE;
73
      mmc_multi_block_start_write(fat.currentSectorNr);
74
    #endif
75
    fat.bufferDirty = TRUE;                  // puffer dirty weil geschrieben und noch nicht auf karte.
76
    return MMC_FILE_NEW;
77
  }
78
  #endif
79
80
81
  #if (MMC_WRITE==FALSE)
82
    return MMC_FILE_NOT_EXISTS;                // wird nur bei readonly zurueckgegeben, wenn datei nicht gefunden wurde.
83
  #endif
84
85
}
86
87
88
//*******************************************************************************************************************************
89
// schließt die datei operation ab. eigentlich nur noetig wenn geschrieben/ueberschrieben wurde. es gibt 2 moeglichkeiten :
90
// 1. die datei wird geschlossen und es wurde über die alte datei länge hinaus geschrieben.
91
// 2. die datei wird geschlossen und man war innerhalb der datei groeße, dann muss nur der aktuelle sektor geschrieben werden.
92
// der erste fall ist komplizierter, weil ermittelt werden muss wie viele sektoren neu beschrieben wurden um diese zu verketten
93
// und die neue datei laenge muss ermitt weden. abschließend wird entweder (fall 2) nur der aktuelle sektor geschrieben, oder
94
// der aktuallisierte datei eintrag und die cluster (diese werden verkettet, siehe fileUpdate() ).
95
//*******************************************************************************************************************************
96
unsigned char ffclose(){
97
98
  #if (MMC_MULTI_BLOCK==TRUE && MMC_OVER_WRITE==FALSE)
99
    if(multiblock_flag == TRUE){
100
      mmc_multi_block_stop_read();   // stoppen von multiblock aktion
101
    }
102
    else{
103
      mmc_multi_block_stop_write();   // stoppen von multiblock aktion
104
    }
105
  #endif
106
107
  #if (MMC_WRITE==TRUE)   /** 2 moeglichkeiten beim schließen !!  (lesend spielt keine rolle, nichts muss geupdatet werden) **/
108
    fflushFileData();
109
  #endif
110
111
  fat.cntOfBytes=0;
112
  file.seek=0;
113
114
  return TRUE;
115
}
116
117
118
#if (MMC_WRITE==TRUE)
119
// *******************************************************************************************************************************
120
// füllt grade bearbeiteten  sektor auf, verkette die bis jetzt benutzten cluster. macht datei eintrag update.
121
// *******************************************************************************************************************************
122
void fflushFileData(void){
123
124
  unsigned long int save_length;
125
  unsigned long int save_currentSectorNr;
126
  unsigned short   save_cntOfBytes;
127
  unsigned short   row;
128
129
  #if (MMC_ENDIANNESS_LITTLE == TRUE)
130
    void         *psector;
131
  #else
132
    unsigned char     *psector;
133
  #endif
134
135
  /** 2 moeglichkeiten ab hier **/
136
  /** 1.) es wurde über die alte datei groeße hinaus geschrieben **/
137
  if( file.length < file.seek+fat.cntOfBytes )  {
138
139
    save_length = file.seek + fat.cntOfBytes;
140
    save_currentSectorNr = fat.currentSectorNr;
141
142
    // wenn fat.cntOfBytes == 0 ist der sektor gerade vorher schon geschrieben worden oder es ist noch nichts hinein geschrieben worden. dann wert so setzten, dass die schleife uebersprungen wird
143
    save_cntOfBytes = fat.cntOfBytes==0 ? 512 : fat.cntOfBytes;
144
    while( save_cntOfBytes < 512 ){            // sektor ist beschrieben worden, daher rest mit 00 fuellen
145
      fat.sector[save_cntOfBytes] = 0x00;       // beschreibt ungenutzte bytes mit 0x00
146
      save_cntOfBytes+=1;
147
      fat.bufferDirty = TRUE;
148
    }
149
150
    // cluster chain verketten, dann dateieitrag mit neuer groeße updaten!
151
    fat_setClusterChain(fat_secToClust(fat.startSectors),fat_secToClust(fat.currentSectorNr));  // verketten der geschriebenen cluster
152
153
    // dateigroeße updaten !!
154
    fat_loadSector(file.entrySector);                  // laden des sektors mit dem dateieintrag zwecks update :)
155
    row = file.row;
156
    row <<=5;
157
    psector =& fat.sector[row+28];
158
159
    #if (MMC_ENDIANNESS_LITTLE == TRUE)
160
      *(unsigned long int*)psector = save_length;
161
    #else
162
      *psector++ = save_length;
163
      *psector++ = save_length >> 8;
164
      *psector++ = save_length >> 16;
165
      *psector   = save_length >> 24;
166
    #endif
167
168
    file.length = save_length;                      // die richtige groeße sichern. wurde ja ueber alte dateigroeße hinaus geschrieben
169
    fat.startSectors = save_currentSectorNr;              // da die sektoren bis zu save_currentSectorNr schon verkettet wurden, reicht es jetzt die kette ab da zu betrachten.
170
171
    // dafuer sorgen, dass der sektor mit dem geaenderten dateieintrag geschrieben wird, beim neuladen. datensektor der datei neuladen, falls noch weitere bytes geschrieben werden.
172
    fat.bufferDirty = TRUE;
173
    fat_loadSector( save_currentSectorNr );
174
  }
175
176
  /** 2.) es wurde nicht über die alte datei groeße hinaus geschrieben **/
177
  else if( fat.bufferDirty == TRUE){
178
    fat_writeSector( fat.currentSectorNr );    // einfach den gerade bearbeiteten sektor schreiben reicht, alle dateiinfos stimmen weil nicht ueber die alte groeße hinaus geschrieben
179
  }
180
181
182
}
183
#endif
184
185
#if (MMC_SEEK==TRUE)
186
// *******************************************************************************************************************************
187
// offset byte wird übergeben. es wird durch die sektoren der datei gespult (gerechnet), bis der sektor mit dem offset byte erreicht
188
// ist, dann wird der sektor geladen und der zaehler für die bytes eines sektors gesetzt. wenn das byte nicht in den sektoren ist,
189
// die "vorgesucht" wurden, muessen noch weitere sektoren der datei gesucht werden (sec > fat.endSectors).
190
// *******************************************************************************************************************************
191
void ffseek(unsigned long int offset){
192
193
  unsigned long int sectors;                // zum durchgehen durch die sektoren der datei
194
195
  #if (MMC_MULTI_BLOCK==TRUE && MMC_OVER_WRITE==FALSE)
196
    unsigned char seek_end;
197
    seek_end = FALSE;
198
199
    if(offset == file.length) {      // zum ende spulen, kann dann nur schreiben sein...
200
      seek_end = TRUE;
201
    }
202
    if(multiblock_flag == FALSE){
203
      mmc_multi_block_stop_write();
204
    }
205
    else {
206
      mmc_multi_block_stop_read();
207
    }
208
  #endif
209
210
  #if (MMC_OVER_WRITE==TRUE && MMC_WRITE==TRUE)
211
    fflushFileData();                // fat verketten und datei update auf der karte !
212
  #endif
213
214
  fat_getFatChainClustersInRow(file.firstCluster);  // suchen von anfang der cluster chain aus, das geht nicht vom ende zum anfang oder so, weil es eine einfach verkettete liste ist !
215
  sectors = fat.startSectors;                // sektor variable zum durchgehen durch die sektoren
216
  file.seek=0;                    // weil auch von anfang an der chain gesucht wird mit 0 initialisiert
217
218
  // suchen des sektors in dem offset ist
219
  while( offset>=512 ){
220
    sectors += 1;                  // da byte nicht in diesem sektor ist, muss hochgezählt werden
221
    offset -= 512;                  // ein sektor weniger in dem das byte sein kann
222
    file.seek += 512;                // file.seek update, damit bei ffclose() die richtige leange herauskommt
223
    fat.cntSecs -= 1;                // damit die zu lesenden/schreibenden sektoren in einer reihe stimmen
224
    if ( fat.cntSecs==0 ){              // es müssen mehr sektoren der datei gesucht werden. sektoren in einer reihe durchgegangen
225
      fat_getFatChainClustersInRow(fat_getNextCluster( file.lastCluster ) );  // suchen von weiteren sektoren der datei in einer reihe
226
      sectors = fat.startSectors;            // setzen des 1. sektors der neu geladenen, zum weitersuchen !
227
    }
228
  }
229
230
  fat_loadSector(sectors);                // sektor mit offset byte laden
231
  fat.cntOfBytes = offset;              // setzen des lese zaehlers
232
233
  #if (MMC_MULTI_BLOCK==TRUE && MMC_OVER_WRITE==FALSE)
234
    if(seek_end == TRUE) {
235
      mmc_multi_block_start_write(sectors);      // starten von multiblock aktion
236
      fat.bufferDirty = TRUE;
237
    }
238
    else {
239
      mmc_multi_block_start_read(sectors);      // starten von multiblock aktion
240
    }
241
  #endif
242
}
243
#endif
244
245
246
#if (MMC_CD==TRUE)
247
// *******************************************************************************************************************************
248
// wechselt verzeichniss. start immer im root Dir.
249
// es MUSS in das direktory gewechselt werden, in dem die datei zum lesen/schreiben ist !
250
// *******************************************************************************************************************************
251
unsigned char ffcd( unsigned char name[]){
252
253
  if(name[0]==0){                  // ZUM ROOTDIR FAT16/32
254
    fat.dir=0;                  // root dir
255
    return TRUE;
256
  }
257
258
  if(TRUE==fat_loadFileDataFromDir(name)){    // NICHT ROOTDIR  (fat16/32)
259
    fat.dir=file.firstCluster;          // zeigt auf 1.cluster des dir  (fat16/32)
260
    return TRUE;
261
  }
262
263
  return FALSE;                  // dir nicht gewechselt (nicht da?) !!
264
}
265
266
//*******************************************************************************************************************************
267
// wechselt in das parent verzeichniss (ein verzeichniss zurück !)
268
// die variable fat.dir enthält den start cluster des direktory in dem man sich grade befindet, anhand diesem,
269
// kann der "." bzw ".." eintrag im ersten sektor des direktory ausgelesen und das parent direktory bestimmt werden.
270
//*******************************************************************************************************************************
271
unsigned char ffcdLower(void){
272
273
  if(fat.dir==0)return FALSE;        // im root dir, man kann nicht hoeher !
274
275
  fat_loadSector(fat_clustToSec(fat.dir));  // laed 1. sektor des aktuellen direktory.
276
  fat_loadRowOfSector(1);          // ".." eintrag (parent dir) ist 0 wenn parent == root
277
  fat.dir=file.firstCluster;        // dir setzen
278
279
  return TRUE;
280
}
281
#endif
282
283
284
#if (MMC_LS==TRUE)
285
// *******************************************************************************************************************************
286
// zeigt reihen eines clusters an, wird für ffls benoetigt !
287
// es wird ab dem start sektor start_sec, der dazugehoerige cluster angezeigt. geprüft wird ob es ein richtiger
288
// eintrag in der reihe ist (nicht geloescht, nicht frei usw). die sektoren des clusters werden nachgeladen.
289
// die dateien werden mit namen und datei groeße angezeigt.
290
// *******************************************************************************************************************************
291
static void lsRowsOfClust (fptr uputs_ptr,unsigned long int start_sec){
292
293
  unsigned short row;        // reihen
294
  unsigned char sec;        // sektoren
295
  unsigned char tmp[11];      // tmp string zur umwandlung
296
  unsigned char i;          // um dateinamen zu lesen
297
298
  sec=0;
299
  do{
300
    fat_loadSector( start_sec + sec );  // sektoren des clusters laden
301
    for( row=0; row<512; row+=32 ){    // geht durch reihen des sektors
302
303
      if( (fat.sector[row+11]==0x20||fat.sector[row+11]==0x10) && (fat.sector[row]!=0xE5 && fat.sector[row]!=0x00) ){
304
        for( i=0 ; i<10 ; i++ ){
305
          tmp[i]=fat.sector[row+i];
306
        }
307
        tmp[i]='\0';
308
        fat_loadRowOfSector(row);    // reihe eines sektors (auf den puffer) laden
309
        uputs_ptr(tmp);
310
311
        uputs_ptr((unsigned char*)" ");
312
        ultoa(file.length,(char*)tmp,10);
313
        uputs_ptr(tmp);
314
        uputs_ptr((unsigned char*)"\n");
315
      }
316
    }
317
  }while( ++sec < fat.secPerClust );
318
}
319
320
// *******************************************************************************************************************************
321
// zeigt inhalt eines direktory an.
322
// unterscheidung ob man sich im rootDir befindet noetig, weil bei fat16 im root dir eine bestimmt anzahl sektoren durchsucht
323
// werden müssen und bei fat32 ab einem start cluster ! ruft lsRowsOfClust auf um cluster/sektoren anzuzeigen.
324
// *******************************************************************************************************************************
325
void ffls(fptr uputs_ptr){
326
327
  unsigned char     sectors;  // variable um durch sektoren zu zaehlen
328
  unsigned long int   clusters;  // variable um durch cluster des verzeichnisses zu gehen
329
330
  // bestimmen ab welchem cluster eintraege angezeigt werden sollen, bzw in welchem ordner man sich befindet
331
  clusters = fat.dir==0?fat.rootDir:fat.dir;
332
333
  // root-dir fat16 nach eintrag durchsuchen. es bleiben noch 3 moeglichkeiten: nicht root-dir fat16, nicht root-dir fat32 und root-dir fat32
334
  if(fat.dir==0 && fat.fatType==16){
335
    sectors = 0;
336
    do{
337
      // root-dir eintraege anzeigen
338
      lsRowsOfClust( uputs_ptr, clusters + sectors );
339
      sectors += fat.secPerClust;
340
    }while( sectors < (unsigned char)32 );
341
  }
342
343
  // root-dir fat32 oder nicht root-dir fat32/16, nach eintrag durchsuchen
344
  else {
345
    // durch cluster des verzeichnisses gehen und eintraege anzeigen
346
    while(!((clusters>=0x0ffffff8&&fat.fatType==32)||(clusters>=0xfff8&&fat.fatType==16))){    // prueft ob weitere sektoren zum lesen da sind (fat32||fat16)
347
      lsRowsOfClust( uputs_ptr, fat_clustToSec(clusters) );                    // zeigt reihen des clusters an
348
      clusters = fat_getNextCluster(clusters);                        // liest naechsten cluster des dir-eintrags (unterverzeichniss groeßer 16 einträge)
349
    }
350
  }
351
352
}
353
#endif
354
355
356
357
#if (MMC_WRITE==TRUE && MMC_MKDIR==TRUE)
358
// *******************************************************************************************************************************
359
// erstellt einen dir eintrag im aktuellen verzeichniss.
360
// prüft ob es den den dir-namen schon gibt, dann wird nichts angelegt.
361
// wenn ok, dann wird ein freier cluster gesucht, als ende markiert, der eintrag ins dir geschrieben.
362
// dann wird der cluster des dirs aufbereitet. der erste sektor des clusters enthält den "." und ".." eintrag.
363
// der "." hat den 1. cluster des eigenen dirs. der ".." eintrag ist der 1. cluster des parent dirs.
364
// ein dir wird immer mit 0x00 initialisiert ! also alle einträge der sektoren des clusters ( bis auf . und .. einträge)!
365
// *******************************************************************************************************************************
366
void ffmkdir( unsigned char name[]){
367
368
  unsigned char i;                // variable zum zaehlen der sektoren eines clusters.
369
  unsigned int j;                // variable zum zaehlen der sektor bytes auf dem puffer fat.sector.
370
371
  if(TRUE==fat_loadFileDataFromDir(name))      // prueft ob dirname im dir schon vorhanden, wenn ja, abbruch !
372
    return ;
373
374
  // cluster in fat setzen, und ordner eintrg im aktuellen verzeichniss machen.
375
  fat_getFreeClustersInRow(2);                  // holt neue freie cluster, ab 2 ...
376
  fat_setCluster(fat_secToClust(fat.startSectors),0x0fffffff);  // fat16/32 cluster chain ende setzen.  (neuer ordner in fat)
377
  file.firstCluster = fat_secToClust(fat.startSectors);      // damit fat_makeFileEntry den cluster richtig setzen kann
378
  fat_makeFileEntry(name,0x10);         // macht dir eintrag im aktuellen verzeichniss (legt ordner im partent verzeichniss an)
379
380
  // aufbereiten des puffers
381
  j=511;
382
  do{
383
    fat.sector[j]=0x00;            //schreibt puffer fat.sector voll mit 0x00==leer
384
  }while(j--);
385
386
  // aufbereiten des clusters
387
  for(i=1;i<fat.secPerClust;i++){        // ein dir cluster muss mit 0x00 initialisiert werden !
388
    fat_writeSector(fat.startSectors+i);  // loeschen des cluster (ueberschreibt mit 0x00), wichtig bei ffls!
389
  } 
390
391
  // aufbereiten des neuen dir sektors mit "." und ".." eintraegen !
392
  file.row=0;
393
  fat_makeSfnDataEntry((unsigned char*)".           ",0x10,file.firstCluster,0);  // macht "." eintrag des dirs
394
  file.row=1;
395
  fat_makeSfnDataEntry((unsigned char*)"..          ",0x10,fat.dir,0);      // macht ".." eintrag des dirs
396
397
  // "." und ".." eintrag auf karte schreiben
398
  mmc_write_sector(fat.startSectors,fat.sector);
399
}
400
#endif
401
402
403
404
#if (MMC_WRITE==TRUE && MMC_RM==TRUE)
405
//*******************************************************************************************************************************
406
// loescht datei/ordner aus aktuellem verzeichniss, wenn es die/den datei/ordner gibt.
407
// loescht dateien und ordner rekursiv !
408
//*******************************************************************************************************************************
409
unsigned char ffrm( unsigned char name[] ){
410
411
  #if(MMC_RM_FILES_ONLY==FALSE)
412
    unsigned long int parent;    // vaterverzeichnis cluster
413
    unsigned long int own;      // cluster des eigenen verzeichnis
414
    unsigned long int clustsOfDir;  // um durch die cluster eines dirs zu gehen
415
    unsigned char cntSecOfClust;  // um durch die sektoren eines clusters zu gehen
416
  #endif
417
418
  unsigned short row;        // um durch die reihen eines sektors zu gehen. springt immer auf das anfangsbyte eines eintrags
419
  unsigned char fileAttrib;      // zum sichern des dateiattributs
420
421
  // datei/ordner nicht vorhanden, dann nicht loschen...
422
  if(FALSE==fat_loadFileDataFromDir(name)){
423
    return FALSE;
424
  }
425
426
  // reihe zu byte offset umrechnen, attribut sichern. anhand des attributs wird spaeter weiter entschieden
427
  row=file.row;
428
  row=row<<5;
429
  fileAttrib = fat.sector[row+11];
430
431
  #if(MMC_RM_FILES_ONLY==TRUE)
432
    // keine datei, also abbruch !
433
    if(fileAttrib!=0x20) return FALSE;
434
  #endif
435
436
  //////// ob ordner oder datei, der sfn und lfn muss geloescht werden!
437
  fat.bufferDirty = TRUE;            // damit beim laden der geaenderte puffer geschrieben wird
438
  do{
439
    fat.sector[row]=0xE5;
440
    if( row==0 ){              // eintraege gehen im vorherigen sektor weiter
441
      fat_loadSector(fat.lastSectorNr);  // der davor ist noch bekannt. selbst wenn der aus dem cluster davor stammt.
442
      fat.bufferDirty = TRUE;
443
      row=512;              // da nochmal row-=32 gemacht wird, kommt man so auf den anfang der letzten zeile
444
    }
445
    row -= 32;
446
  }while(  fat.sector[row+11]==0x0f );    // geht durch alle reihen bis neuer eintrag erkannt wird...
447
448
  #if(MMC_RM_FILES_ONLY==TRUE)
449
    fat_delClusterChain(file.firstCluster);  // loescht die zu der datei gehoerige cluster-chain aus der fat.
450
  #else
451
    //// ist datei. dann nur noch cluster-chain loeschen und fertig.
452
    if( fileAttrib == 0x20 ){
453
      fat_delClusterChain(file.firstCluster);  // loescht die zu der datei gehoerige cluster-chain aus der fat.
454
    }
455
    //// ist ordner. jetzt rekursiv durch alle zweige/aeste des baums, den dieser ordner evtl. aufspannt, und alles loeschen!
456
    else{
457
      clustsOfDir = file.firstCluster;
458
      // jetzt eigentlichen ordnerinhalt rekursiv loeschen!
459
      do{
460
        do{
461
          cntSecOfClust=0;
462
          do{
463
            fat_loadSector( fat_clustToSec(clustsOfDir) + cntSecOfClust );    // in ordner wechseln / neuen cluster laden zum bearbeiten
464
            row=0;
465
            do{
466
              // nach einem leeren eintrag kommt nix mehr. cntSecOfClust wird auch gesetzt, damit man auch durch die naechste schleife faellt!
467
              if(fat.sector[row]==0x00){
468
                cntSecOfClust = fat.secPerClust;
469
                break;
470
              }
471
472
              // sfn eintrag erkannt. eintrag geloescht markieren, cluster chain loeschen, diesen sektor neu laden!
473
              if( fat.sector[row]!=0xE5 && fat.sector[row+11]!=0x10 && fat.sector[row+11]!=0x0F ){
474
                fat_loadRowOfSector(row);
475
                fat.sector[row] = 0xE5;    // hier evtl. nur pruefen ob file.firstCluster nicht schon in der fat geloescht ist...
476
                fat.bufferDirty = TRUE;
477
                fat_delClusterChain(file.firstCluster);
478
                fat_loadSector( fat_clustToSec(clustsOfDir) + cntSecOfClust );  // aktuellen sektor wieder laden...wurde bei fat_delClusterChain geaendert
479
              }
480
481
              // punkt eintrag erkannt, own und parent sichern!
482
              if( fat.sector[row]=='.' && row==0 && fat.sector[row+11]==0x10){
483
                fat_loadRowOfSector(row);
484
                own = file.firstCluster;
485
                fat_loadRowOfSector(row+32);
486
                parent = file.firstCluster;
487
              }
488
489
              // ordner erkannt. jetzt ordner eintrag loeschen, hinein wechseln und alles von vorne...
490
              if(  fat.sector[row]!='.' && fat.sector[row]!=0xE5 && fat.sector[row+11]==0x10){
491
                fat_loadRowOfSector(row);
492
                fat.sector[row] = 0xE5;
493
                fat.bufferDirty = TRUE;
494
                clustsOfDir = file.firstCluster;
495
                fat_loadSector( fat_clustToSec(clustsOfDir) );  // hier wird in das dir gewechselt!
496
                row = 0;
497
                cntSecOfClust = 0;
498
                continue;
499
              }
500
501
              row += 32;
502
              }while( row < 512 );
503
          }while( ++cntSecOfClust < fat.secPerClust );
504
          clustsOfDir = fat_getNextCluster(clustsOfDir);    // holen des folgeclusters um durch die chain zu gehen
505
        }while( !((clustsOfDir>=0x0ffffff8 && fat.fatType==32) || (clustsOfDir==0xfff8 && fat.fatType==16)) );    // geht durch cluster des dirs.
506
507
        // hier ist man am ende eines astes. also ast loeschen und zuruck zum stamm :)
508
        fat_delClusterChain(own);
509
510
        // stamm ist ein weiterer ast wenn parent!=fat.dir. ast wird oben geladen und weiter verarbeitet
511
        clustsOfDir = parent;
512
513
      }while(parent!=fat.dir);
514
    }
515
  #endif
516
  return TRUE;        // alles ok, datei/ordner geloescht !
517
}
518
#endif
519
520
521
// *******************************************************************************************************************************
522
// liest 512 bytes aus dem puffer fat.sector. dann werden neue 512 bytes der datei geladen, sind nicht genuegend verkettete
523
// sektoren in einer reihe bekannt, wird in der fat nachgeschaut. dann werden weiter bekannte nachgeladen...
524
// *******************************************************************************************************************************
525
unsigned char ffread(void){
526
527
  unsigned long int nc;
528
529
  if( fat.cntOfBytes == 512 ){              // EINEN SEKTOR GLESEN (ab hier 2 moeglichkeiten !)
530
531
    fat.cntSecs-=1;                    // anzahl der sektoren am stück werden weniger, bis zu 0 dann müssen neue gesucht werden...
532
533
    if( 0==fat.cntSecs ){                 //1.) noetig mehr sektoren der chain zu laden (mit ein bisschen glück nur alle 512*MAX_CLUSTERS_IN_ROW bytes)
534
535
      #if (MMC_MULTI_BLOCK==TRUE && MMC_OVER_WRITE==FALSE)
536
        mmc_multi_block_stop_read ();          // stoppen von multiblock aktion
537
      #endif
538
539
      nc = fat_secToClust( fat.currentSectorNr );    // umrechnen der aktuellen sektor position in cluster
540
      nc = fat_getNextCluster(nc);          // in der fat nach neuem ketten anfang suchen
541
      fat_getFatChainClustersInRow(nc);        // zusammenhängende cluster/sektoren der datei suchen
542
      fat.currentSectorNr = fat.startSectors - 1;    // hier muss erniedrigt werden, da nach dem if immer ++ gemacht wird
543
544
      #if (MMC_MULTI_BLOCK==TRUE && MMC_OVER_WRITE==FALSE)
545
        mmc_multi_block_start_read (fat.startSectors);  // starten von multiblock lesen ab dem neu gesuchten start sektor der kette.
546
      #endif
547
    }
548
549
    fat.cntOfBytes = 0;
550
551
    #if (MMC_MULTI_BLOCK==TRUE && MMC_OVER_WRITE==FALSE)
552
      fat.currentSectorNr+=1;
553
      mmc_multi_block_read_sector (fat.sector);      //2.) bekannte sektoren reichen noch, also einfach nachladen..
554
    #else
555
      fat_loadSector(fat.currentSectorNr+1);        //2.) die bekannten in einer reihe reichen noch.(nur alle 512 bytes)
556
    #endif
557
  }
558
  return fat.sector[fat.cntOfBytes++];
559
}
560
561
562
563
#if (MMC_OVER_WRITE==FALSE && MMC_WRITE==TRUE)      // nicht ueberschreibende write funktion
564
//*******************************************************************************************************************************
565
// schreibt 512 byte bloecke auf den puffer fat.sector. dann wird dieser auf die karte geschrieben. wenn genügend feie
566
// sektoren zum beschreiben bekannt sind(datenmenge zu groß), muss nicht in der fat nachgeschaut werden. sollten nicht genügend
567
// zusammenhängende sektoren bekannt sein, werden die alten verkettet und neue gesucht. es ist noetig sich den letzten bekannten
568
// einer kette zu merken -> file.lastCluster, um auch nicht zusammenhängende cluster verketten zu koennen (fat_setClusterChain macht das)!
569
//*******************************************************************************************************************************
570
void ffwrite( unsigned char c){
571
572
  fat.sector[fat.cntOfBytes++] = c;              // schreiben des chars auf den puffer sector und zähler erhoehen (pre-increment)
573
574
  if( fat.cntOfBytes==512 ){                /** SEKTOR VOLL ( 2 moeglichkeiten ab hier !) **/
575
    file.seek += 512;                      // position in der datei erhoehen, weil grade 512 bytes geschrieben
576
    fat.cntOfBytes = 0;                        // rücksetzen des sektor byte zählers
577
    fat.cntSecs -= 1;                      // noch maximal cntSecs sekoren zum beschreiben bekannt...
578
579
    #if (MMC_MULTI_BLOCK==TRUE)
580
      mmc_multi_block_write_sector(fat.sector);    /** 1.) genügend leere zum beschreiben bekannt **/
581
    #else
582
      mmc_write_sector(fat.currentSectorNr,fat.sector);      //genügend leere zum beschreiben bekannt
583
    #endif
584
585
    fat.currentSectorNr += 1;                    // nächsten sektor zum beschreiben.
586
587
    if( fat.cntSecs==0 ){                /** 2.) es ist noetig, neue freie zu suchen und die alten zu verketten (mit ein bischen glück nur alle 512*MAX_CLUSTERS_IN_ROW bytes) **/
588
      #if (MMC_MULTI_BLOCK==TRUE)
589
        mmc_multi_block_stop_write();
590
      #endif
591
      fat.bufferDirty = FALSE;                  // sonst würde das suchen von clustern wieder eine schreiboperation ausloesen... siehe fat_writeSector
592
      fat_setClusterChain( fat_secToClust(fat.startSectors) , fat_secToClust(fat.currentSectorNr-1) );  // verketten der beschriebenen
593
      fat_getFreeClustersInRow(file.lastCluster);          // suchen von leeren sektoren.
594
      fat.currentSectorNr = fat.startSectors;            // setzen des 1. sektors der neuen reihe zum schreiben.
595
      fat.bufferDirty = TRUE;
596
      #if (MMC_MULTI_BLOCK==TRUE)
597
        mmc_multi_block_start_write(fat.currentSectorNr);
598
      #endif
599
    }
600
  }
601
}
602
#else                // ueberschreibende write funktion
603
//*******************************************************************************************************************************
604
// schreibt 512 byte bloecke auf den puffer fat.sector. dann wird dieser auf die karte geschrieben. wenn genuegend feie
605
// sektoren zum beschreiben bekannt sind, muss nicht in der fat nachgeschaut werden. sollten nicht genuegend zusammenhaengende
606
// sektoren bekannt sein(datenmenge zu groß), werden die alten verkettet und neue gesucht. es ist noetig sich den letzten bekannten einer
607
// kette zu merken -> file.lastCluster, um auch nicht zusammenhaengende cluster verketten zu koennen (fat_setClusterChain macht das)!
608
// es ist beim überschreiben noetig, die schon beschriebenen sektoren der datei zu laden, damit man die richtigen daten
609
// hat. das ist bloed, weil so ein daten overhead von 50% entsteht. da lesen aber schneller als schreiben geht, verliert man nicht 50% an geschwindigkeit.
610
//*******************************************************************************************************************************
611
void ffwrite( unsigned char c){
612
  
613
  fat.sector[ fat.cntOfBytes++ ]=c;              // schreiben des chars auf den puffer sector und zähler erhoehen (pre-increment)
614
615
  if( fat.cntOfBytes==512 ){                  /** SEKTOR VOLL ( 3 moeglichkeiten ab hier !) **/
616
617
    fat.cntOfBytes = 0;                        // ruecksetzen des sektor byte zählers.
618
    file.seek += 512;                      // position in der datei erhoehen, weil grade 512 bytes geschrieben.
619
    mmc_write_sector( fat.currentSectorNr,fat.sector );    /** 1.) vollen sektor auf karte schreiben, es sind noch freie sektoren bekannt**/
620
    fat.currentSectorNr +=1;                  // naechsten sektor zum beschreiben.
621
    fat.cntSecs -=1;
622
623
    if( fat.cntSecs==0 ){                    // ende der bekannten in einer reihe erreicht (freie oder verkettete)
624
      if( file.seek > file.length ){            /** 2.) außerhalb der datei, jetzt ist es noetig die beschriebenen cluster zu verketten und neue freie zu suchen  **/
625
        fat.bufferDirty = FALSE;              // damit nicht durch z.b. fat_getNextCluster nochmal dieser sektor gescchrieben wird, siehe fat_loadSector
626
        fat_setClusterChain( fat_secToClust(fat.startSectors) , fat_secToClust(fat.currentSectorNr-1) );  // verketten der beschriebenen.
627
        fat_getFreeClustersInRow( file.lastCluster );    // neue leere sektoren benoetigt, also suchen.
628
        fat.currentSectorNr = fat.startSectors;        // setzen des 1. sektors der neuen reihe zum schreiben.
629
        fat.bufferDirty = TRUE;
630
      }
631
      else {                        /** 3.) noch innerhalb der datei, aber es muessen neue verkettete cluster gesucht werden, zum ueberschreiben **/
632
        fat_getFatChainClustersInRow( fat_getNextCluster(file.lastCluster) );    // noch innerhalb der datei, deshlab verkettete suchen.
633
        fat.currentSectorNr = fat.startSectors;        // setzen des 1. sektors der neuen reihe zum schreiben.
634
      }
635
    }
636
    if( file.seek<=file.length ){
637
      mmc_read_sector(fat.currentSectorNr,fat.sector);    // wegen ueberschreiben, muss der zu beschreibende sektor geladen werden (zustand 3)...
638
    }
639
  }
640
}
641
#endif
642
643
644
#if (MMC_WRITE_STRING==TRUE && MMC_WRITE==TRUE)
645
// *******************************************************************************************************************************
646
// schreibt string auf karte, siehe ffwrite()
647
// ein string sind zeichen, '\0' bzw. 0x00 bzw dezimal 0 wird als string ende gewertet !!
648
// wenn sonderzeichen auf die karte sollen, lieber ffwrite benutzen!
649
// *******************************************************************************************************************************
650
void ffwrites( unsigned char *s ){
651
    while (*s){
652
      ffwrite(*s++);
653
    }
654
    fat.bufferDirty = TRUE;
655
  }
656
#endif