Subversion Repositories Projects

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
231 killagreg 1
#include <stdio.h>
2
#include <avr/io.h>
3
#include "fat16.h"
4
#include "sdc.h"
5
#include "printf_P.h"
6
 
7
 
8
//________________________________________________________________________________________________________________________________________
9
// Module name:                 fat16.c
10
// Compiler used:               avr-gcc 3.4.5
11
// Last Modifikation:   28.03.2008
12
// Version:                             1.25
13
// Authors:                             Stephan Busker
14
// Description:                 Source files for FAT16 implementation with read and write-access using AVR-Mikrocontrollers
15
//                                              Copyright (C) 2007 Stephan Busker
16
//........................................................................................................................................
17
// Functions:                   extern u8       FAT16_Init(void);
18
//                                              u8                      fopen_(s8 *fname,s8 mode, File *file);
19
//                                              void            fclose_(File *file);
20
//                                              u32             fread_(void *buffer, u32 size, u32 count, File *file);
21
//                                              u32             fwrite_(void *buffer, u32 size, u32 count, File *file);
22
//                                              s16             fseek_(File *file, s32 offset, s16 origin);
23
//                                      s8                      fgets_(s8 *string, s16 count, File *file);
24
//                                              u8                      fputchar_(File *file,s8 c);
25
//                                              u8                      fputs_(File *file,s8 *string);
26
//                                              s8 *            fgets(s8 *, s16, File);
27
//                                              u8                      fexist_(u8*, File *file);
28
//                                              u8                      mkdir__(s8 *name);
29
//                                              u8                      chdir__(s8 *name);
30
//                                              u8                      findfirst_(s8 *fname, Find *item, u8 attribute);
31
//                                              u8                      findnext_(Find *item);
32
//                                              u8                      fdelete_(s8 *fname)
33
//                                              u8                      rmdir_(s8 *dname)
34
//........................................................................................................................................
35
// ext. functions:              extern u8 SDC_GetSector  (u32,u8 *);
36
//                                              extern u8 SDC_PutSector (u32,u8 *);
37
//........................................................................................................................................
38
//
39
// URL:                                 www.Mikro-Control.de
40
// mailto:                              stephan.busker@mikro-control.de
41
//________________________________________________________________________________________________________________________________________
42
 
43
u8 text[80];
44
 
45
 
46
//________________________________________________________________________________________________________________________________________
47
//
48
// Global variables needed for read- or write-acces to the FAT16- filesystem.
49
//
50
//________________________________________________________________________________________________________________________________________
51
 
52
u8              SectorsPerCluster               = 0;                    // how many sectors does a cluster contain?
53
u8              FatCopies                               = 0;                    // Numbers of copies of the FAT
54
u16             PossibleRootEntries     = 0;                    // Possible number of entries in the root directory.
55
u16             SectorsPerFat                   = 0;                    // how many sectors does a fat16 contain?
56
u32             ReservedSectors                 = 0;                    // Sectors reserved by the filesystem.
57
u32             FirstPartitionSector    = 0;                    // Distance in sectors between the first partition and the master bootrecord.
58
u32             FileAllocationTable     = 0;                    // pointer to the first FAT
59
u32             RootDirectory                   = 0;                    // Pointer to the rootdirectory of the first partition.
60
u32             FirstDataCluster                = 0;                    // Pointer to the first cluster containing data (cluster0).
61
u32             CWD                                             = 0;                    // Pointer startcluster to the current working directory
62
 
63
 
64
struct DirEntry         *DirectoryEntry;                        // Pointer to an entry of the directory.
65
struct FatEntry         *Fat;                                           // Pointer to an entry of the fat (next clusterposition).
66
 
67
File FilePointer[__MAX_FILES_USED];                             // Allocate Memmoryspace for each filepointer used.
68
 
69
 
70
//________________________________________________________________________________________________________________________________________
71
// Funtion:     InitFat16(void);
72
//
73
// Description: This function reads the Masterbootrecord and finds the position of the Volumebootrecord, the FAT and the Rootdirectory
74
//                              and stores the information in global variables.
75
//
76
// Returnvalue: The function returns "0" if the filesystem could not be initialized because no partition was found on the disc.
77
//________________________________________________________________________________________________________________________________________
78
 
79
u8  FAT16_Init(void)
80
{
81
        u8 retvalue = 0;
82
    u8  cnt     = 0;
83
        struct VBR_Entry *VBR;                                                                          // Pointer to the VolumeBootRecord.
84
        struct MBR_Entry *MBR;                                                                          // Pointer to the masterbootrecord.
85
        File *file;
86
 
87
        for(cnt=0;cnt<__MAX_FILES_USED;cnt++)
88
        {
89
                FilePointer[cnt].state = _UNUSED;                                                               // declare the filepointers as unused.
90
        }
91
 
92
        file = &FilePointer[0];
93
 
94
        while((SDC_Init() != 0) && (cnt++<200));                                        // initialise the sdcard.
95
        if(cnt <200)                                                                                            //sdcard initialised succesfully
96
        {
97
                SDC_GetSector((u32)_MBR_SECTOR,file->buffer);                   // Read the MasterBootRecord from mmc.
98
                MBR = (struct MBR_Entry *) file->buffer;
99
                FirstPartitionSector = MBR->PartitionEntry1.NoSectorsBeforePartition;
100
                if((MBR->PartitionEntry1.Type == _FAT16_32_MB_BIOS_Extension) ||
101
                   (MBR->PartitionEntry1.Type == _FAT16_ST_32_MB) ||
102
                   (MBR->PartitionEntry1.Type == _FAT16_LT_32_MB))
103
                {
104
                        SDC_GetSector(FirstPartitionSector,file->buffer);               // Read the volume bootrecord from mmc.
105
 
106
                        VBR = (struct VBR_Entry *) file->buffer;                                        // Enter the VBR using the structure VBR_Entry.
107
                        SectorsPerCluster       = VBR->SectorsPerCluster;                       // Number of sectors per cluster. Depends on the memorysize of the sd-card.
108
                        FatCopies                       = VBR->NoFATCopies;                                     // Number of fatcopies.
109
                        PossibleRootEntries = VBR->MaxRootEntries;                              // How many Entries are possible in the rootdirectory (FAT16 allows max. 512 entries).
110
                        SectorsPerFat           = VBR->SectorsPerFAT;                           // The number of sectors per FAT.
111
                        ReservedSectors         = VBR->ReservedSectors;                         // calculate the sectorpositon of the FAT, the Rootdirectory and the first Datacluster.
112
 
113
                        FileAllocationTable     =   (u32)(FirstPartitionSector + (u32)ReservedSectors);                                                 // Calculate the position of the FileAllocationTable.
114
                        RootDirectory           =   (u32)((u32)FileAllocationTable + (u32)((u32)SectorsPerFat*(u32)FatCopies)); // Calculate the position of the Rootdirectory.
115
                        FirstDataCluster        =   (u32)((u32)RootDirectory + ((u32)(PossibleRootEntries>>4)));                                        // Calculate the position of the first datacluster.
116
                        CWD                                     =       RootDirectory;                                                                                                                                  // The actual directory is the rootdirectory.
117
                        retvalue = 1;
118
                }
119
        }
120
        return(retvalue);
121
}
122
 
123
//________________________________________________________________________________________________________________________________________
124
// Funtion:     File * fopen_(u8*, u8 *);
125
//
126
// Description: This function looks for the file in the directory specified by the variable "CWD" of the drive. If the file is found the number of the
127
//                              corrosponding datacluster is returned to main. Only modes 'r' (reading) and 'a' append are implemented yet.
128
//
129
//      Return:         0 = faild to open speicified file
130
//                              1 = file opened
131
//________________________________________________________________________________________________________________________________________
132
 
133
File * fopen_(s8 *fname, s8 mode)
134
{
135
        File *file;
136
 
137
        file = ReserveFilePointer();                                                                                                    // reserve a filepointer.
138
 
139
        if(file != NULL)                                                                                                                                // A free filepointer was found.
140
        {
141
                file->mode      = mode;                                                                                                                 // mode of fileoperation (read,write)
142
 
143
                if(SeekFileInDirectory(fname, file))                                                                            // if file was found
144
                {
145
                        if(mode == 'a')                                                                                                                 // open existing file for writing (append data at the end of the file)
146
                        {
147
                                fseek_(file, 0, SEEK_END);                                                                                      // fseek points to the end of the file
148
                        }
149
                        else if(mode == 'r')
150
                        {
151
                                return(file);
152
                        }
153
                        else
154
                        {
155
                                fclose_(file);
156
                                file = NULL;
157
                        }
158
 
159
                }
160
                else
161
                {
162
                        if((mode == 'a') || (mode == 'w'))                                                                              // specified file doesn't exist so create new file for writing data.
163
                        {
164
                                if(CreateFileInDirectory(fname,file))                                                           // Could an entry for the new file in the rootdirectory be created?
165
                                {
166
                                        return(file);
167
                                }
168
                                else
169
                                {
170
                                        fclose_(file);
171
                                        file = NULL;
172
                                }
173
                        }
174
                }
175
        }
176
        return(file);
177
}
178
 
179
 
180
 
181
//________________________________________________________________________________________________________________________________________
182
// Funtion:     fflush_(File *file);
183
//
184
// Description: This function writes the data already in the buffer but not yet written to the file.
185
//
186
//________________________________________________________________________________________________________________________________________
187
 
188
s16     fflush_(File *file)
189
{
190
        u16 time=0;
191
        u16 date=0;
192
 
193
 
194
        if(file && ((file->mode =='a') || (file->mode =='w')))
195
        {
196
                if(file->byte_index > 0)                                                                                                                        // has data been added to the file?
197
                {
198
                        SDC_PutSector((u32)(file->cluster_pointer + file->sector_index),file->buffer);// save the data still in the buffer
199
                }
200
                SDC_GetSector((u32)file->directory_sector,file->buffer);                                                        // read the directoryentry for this file.
201
                DirectoryEntry = (struct DirEntry *)file->buffer;
202
                DirectoryEntry[file->directory_index].size = (u32) file->filesize;
203
                DirectoryEntry[file->directory_index].time = (u16) time;
204
                DirectoryEntry[file->directory_index].date = (u16) date;
205
                SDC_PutSector((u32)file->directory_sector,file->buffer);
206
        }
207
        return(0);
208
}
209
 
210
//________________________________________________________________________________________________________________________________________
211
// Funtion:     fclose_(File *file);
212
//
213
// Description: This function closes the open file by writing the remaining data from the buffer to the device and entering the filesize
214
//                              in the directory entry.
215
//________________________________________________________________________________________________________________________________________
216
 
217
void fclose_(File *file)
218
{
219
        if(file != NULL)
220
        {
221
                fflush_(file);                                                                                                                                          // save buffered data to the disk
222
        }
223
        FreeFilePointer(file);                                                                                                                                          // and free the filepointer.
224
}
225
 
226
//________________________________________________________________________________________________________________________________________
227
// Funtion:     u32 fread_(void *buffer, s32 size, s32 count, File *file);
228
//
229
// Description: This function reads count objects of the specified size from the actual position of the file to the specified buffer.
230
//
231
// Returnvalue: The function returns the number of objects (not bytes) read from the file.
232
//
233
//________________________________________________________________________________________________________________________________________
234
 
235
u32 fread_(void *buffer, u32 size, u32 count, File *file)
236
{
237
        u32 object_cnt  = 0;                                                                                                            // count the number of objects read from the file.
238
        u32 object_size         = 0;                                                                                                            // count the number of bytes read from the actual object.
239
        u8 *buff_pnt    = 0;                                                                                                            // a pointer to the actual bufferposition.
240
        u8 success      = 1;                                                                                                            // no error occured during read operation to the file.
241
 
242
        buff_pnt = (u8 *) buffer;                                                                                                       // cast the void pointer to an u8 *
243
 
244
        while((object_cnt < count) && success)
245
        {
246
                object_size = size;
247
                while((size > 0) && success)
248
                {
249
                        *buff_pnt = (u8) fgetchar_(file);                                                                       // read a byte from the buffer to the opened file.
250
                        buff_pnt++;
251
                        size--;
252
                }
253
                if(success) object_cnt++;
254
        }
255
 
256
        return(object_cnt);                                                                                                                                     // return the number of objects succesfully read from the file
257
}
258
 
259
//________________________________________________________________________________________________________________________________________
260
// Funtion:     u32 fwrite_(void *buffer, s32 size, s32 count, File *file);
261
//
262
// Description: This function writes count objects of the specified size from the buffer to the actual positon within the file.
263
//
264
// Returnvalue: The function returns the number of objects (not bytes) written to the file.
265
//
266
//________________________________________________________________________________________________________________________________________
267
 
268
u32 fwrite_(void *buffer, u32 size, u32 count, File *file)
269
{
270
        u32 object_cnt  = 0;                                                                                                            // count the number of objects written to the file.
271
        u32 object_size         = 0;                                                                                                            // count the number of bytes written from the actual object.
272
        u8 *buff_pnt    = 0;                                                                                                            // a pointer to the actual bufferposition.
273
        u8 success      = 1;                                                                                                            // no error occured during write operation to the file.
274
 
275
        buff_pnt = (u8 *) buffer;                                                                                                       // cast the void pointer to an u8 *
276
 
277
        while((object_cnt < count) && success)
278
        {
279
                object_size = size;
280
                while((size > 0) && success)
281
                {
282
                        success = fputchar_(file, *buff_pnt);                                                                                   // write a byte from the buffer to the opened file.
283
                        buff_pnt++;
284
                        size--;
285
                }
286
                if(success) object_cnt++;
287
        }
288
 
289
        return(object_cnt);                                                                                                                                     // return the number of objects succesfully written to the file
290
}                                                                                                                                                                                       // (!!!!! objects and not bytes !!!!)
291
 
292
//________________________________________________________________________________________________________________________________________
293
// Funtion:     s16 fseek_(File *, s32, s16)
294
//
295
// Description: This function sets the pointer of the stream relative to the position
296
//                              specified by origin (SEEK_SET, SEEK_CUR, SEEK_END).
297
//
298
//________________________________________________________________________________________________________________________________________
299
 
300
s16 fseek_(File *file, s32 offset, s16 origin)
301
{
302
        s32                     fposition       = 0;
303
        s16                     retvalue        = 1;
304
        u32     temp            = 0;
305
 
306
//......................................................
307
        if(origin == SEEK_SET)                                                                                          // Fileposition relative to the beginning of the file.
308
        {
309
                fposition = 0;
310
        }
311
//......................................................
312
        else if(origin == SEEK_END)                                                                                     // Fileposition relative to the end of the file.
313
        {
314
                fposition  = (s32) file->filesize;
315
        }
316
//......................................................
317
        else if(origin == SEEK_CUR)                                                                                     // Fileposition relative to the current position of the file.
318
        {
319
                fposition = file->fileposition;
320
        }
321
 
322
        fposition += offset;
323
 
324
        if((fposition >= 0) && (fposition <= (s32)file->filesize))              // is the pointer still within the file?
325
        {
326
                retvalue                                = 0;
327
                file->sector_index              = 0;
328
                file->byte_index                = 0;
329
                file->fileposition              = 0;
330
                file->cluster_pointer   = file->start_cluster;
331
 
332
                while(file->fileposition < fposition)
333
                {
334
                        file->fileposition++;
335
                        if(file->byte_index < 511)
336
                        {
337
                                file->byte_index++;
338
                        }
339
                        else
340
                        {
341
                                file->byte_index=0;                                                                             // reading at the beginning of new sector.
342
                                file->sector_index++;                                                                   // continue reading in next sector
343
                                if(file->sector_index >= SectorsPerCluster)                     // When end of cluster is reached, the next datacluster has to be searched in the FAT.
344
                                {
345
                                        if(file->fileposition < fposition)
346
                                        {
347
                                                file->sector_index = 0;                                                 // start reading new cluster at first sector of the cluster.
348
                                                GetNextCluster(file);                                                   // Sets the clusterpointer of the file to the next datacluster.
349
                                        }
350
                                }
351
                        }
352
                }
353
                if(file->byte_index)
354
                {
355
                        temp = (u32)((u32)file->cluster_pointer + (u32)file->sector_index);
356
                        SDC_GetSector((u32)temp,file->buffer);          // FileBuffer will be written at once at the end of the cluster and has to be updated.
357
                }
358
        }
359
        return(retvalue);
360
}
361
 
362
//________________________________________________________________________________________________________________________________________
363
// Funtion:     fgetchar_(File *file);
364
//
365
// Description: This function reads and returns one character from the specified file.
366
//
367
// Returnvalue: The function returns the character read from the specified memorylocation as u8 casted to s16 or EOF.
368
//________________________________________________________________________________________________________________________________________
369
 
370
s16 fgetchar_(File *file)
371
{
372
        s16 c = EOF;
373
        u32 temp1;
374
 
375
        if(file->filesize > 0)                                                                                                          // wen the end of the file is not reached, get the next character.
376
        {
377
                temp1  = (u32)file->cluster_pointer;                                            // calculate the adress of the next character to be read.
378
                temp1 += (u32)file->sector_index;
379
 
380
                if(file->sector_in_buffer != temp1)                                                                     // Has the content of the buffer been modified and has to be updated?
381
                {
382
                        SDC_GetSector((u32)temp1,file->buffer);                                 // Read the calculated cluster.
383
                        file->sector_in_buffer = (u32)temp1;
384
                }
385
                c = (s16) file->buffer[file->byte_index];
386
                file->filesize--;                                                                                                               // decrement the number of characters available.
387
 
388
                if(file->byte_index < 511)                                                                                              // continue reading from this sector until the end of the sector is reached.
389
                {
390
                        file->byte_index++;
391
                }
392
                else                                                                                                                                    // has the end of an sector been reached->
393
                {
394
                        file->byte_index=0;                                                                                                     // continue reading at the beginning -
395
                        file->sector_index++;                                                                                           // of new sector.
396
                        if(file->sector_index >= SectorsPerCluster)                                             // When the end of an cluster is reached, the next datacluster has to be searched in the FAT.
397
                        {
398
                                file->sector_index = 0;                                                                                 // start reading new cluster at first sector of the cluster.
399
                                GetNextCluster(file);                                                                                   // Sets the clusterpointer of the file to the next datacluster.
400
                        }
401
                }
402
        }
403
        return(c);
404
}
405
 
406
//________________________________________________________________________________________________________________________________________
407
// Funtion:     fputchar_(File *file, s8 *);
408
//
409
// Description: This function writes a byte to the specified file and takes care of writing the necessary FAT- Entries.
410
//
411
// Returnvalue: The function returns a value of 0 if the data could not be written.
412
//________________________________________________________________________________________________________________________________________
413
 
414
u8 fputchar_(File *file,s8 c)
415
{
416
        u32 ul_temp  = 0;
417
        u8 retvalue = 1;
418
 
419
    if(file->sector_index >= SectorsPerCluster)                                                                         // if end of the cluster is reached, find next free cluster
420
        {
421
                file->sector_index = 0;
422
                if(!AppendCluster(file)) retvalue = 0;                                                                                  // append a new and free cluster at the end of the file.
423
        }
424
 
425
        file->buffer[file->byte_index] = c;                                                                                             // write databyte into the buffer. The byte will be written to the device at once
426
        if(file->filesize == file->fileposition) file->filesize++;                                                      // a character has been written to the file so the size is inkremented but only when the character has been added at the end of the file.
427
        file->fileposition++;                                                                                                                           // the actual positon within the file.
428
                                                                                                                                                                                // if the buffer contains the complete sectordata.
429
        if(file->byte_index < 511)                                                                                                                      // if the end of this sector is not reached yet
430
        {
431
                file->byte_index++;                                                                                                                             // the next byte will be written to the next byteposition in this sector.
432
        }
433
        else                                                                                                                                                            // otherwise the data in the sectorbuffer will be written to the device and the next sector will be selected.
434
        {
435
                ul_temp  = (u32)file->cluster_pointer;
436
                ul_temp += (u32)file->sector_index;
437
 
438
                SDC_PutSector((u32)ul_temp,file->buffer);
439
                file->byte_index=0;                                                                                                                             // and the next byte will be written at the beginning of this new sector.
440
                file->sector_index++;
441
                if(file->sector_index >= SectorsPerCluster)                                                                     // if end of the cluster is reached, find next free cluster
442
                {
443
                        file->sector_index = 0;
444
                        if(!AppendCluster(file)) retvalue = 0;                                                                          // append a new and free cluster at the end of the file.
445
                }
446
        }
447
        return(retvalue);
448
}
449
 
450
//________________________________________________________________________________________________________________________________________
451
// Funtion:     fputs_(File *file, s8 *string);
452
//
453
// Description: This function writes a string to the specified file.
454
//
455
//________________________________________________________________________________________________________________________________________
456
 
457
u8 fputs_(File *file,s8 * string)
458
{
459
        u8 i=0;
460
 
461
        while(string[i] != 0)
462
        {
463
                fputchar_(file,string[i]);
464
                i++;
465
        }
466
        return(0);
467
}
468
 
469
//________________________________________________________________________________________________________________________________________
470
// Funtion:     s8 * fgets_(s8 *string, s16 count, File *file)
471
//
472
// Description: This function reads a string from the file to the specifies string.
473
//
474
// Returnvalue: A pointer to the string written from the file.
475
//________________________________________________________________________________________________________________________________________
476
 
477
s8 * fgets_(s8 *string, s16 count, File *file)
478
{
479
        s16 buff_pnt = 0;
480
        s16 buff_tmp = 0;
481
        u8 state = 0;                                                                                                                   // Variable used for a statemachine to recognize the end of a line.
482
 
483
        while(count > 1)                                                                                                                                        // read the count-1 characters from the file to the string.
484
        {
485
                buff_tmp = fgetchar_(file);                                                                                                             // read a character from the opened file.
486
                switch(state)
487
                {
488
                        case 0:
489
                                if(buff_tmp == 0x0D) state++;
490
                        break;
491
 
492
                        case 1:
493
                                if(buff_tmp == 0x0A)
494
                                {
495
                                        count = 1;
496
                                }
497
                                state = 0;
498
                        break;
499
                }
500
                if(buff_tmp == EOF) {buff_tmp = 0; count = 1;}                                                                  // is the end of the file reached, terminate the string with zero.
501
                string[buff_pnt] = (s8) buff_tmp;
502
                count--;
503
                buff_pnt++;
504
        }
505
        string[buff_pnt] = 0;
506
        return(string);
507
}
508
 
509
//________________________________________________________________________________________________________________________________________
510
// Funtion:     u8 fexist_(u8*, File *file);
511
//
512
// Description: This function searches the specified file and returns 0 if the file was not found.
513
//
514
//
515
//      Return:         0 = file does not exist
516
//                              1 = file exists
517
//________________________________________________________________________________________________________________________________________
518
 
519
u8 fexist_(s8 *fname)
520
{
521
        File *file;
522
 
523
        file = ReserveFilePointer();
524
 
525
        if(file != NULL)
526
        {
527
                if((file = fopen_(fname,'r'))!= NULL)
528
                {
529
                        fclose_(file);
530
                        return(1);
531
                }
532
                else
533
                {
534
                        return(0);
535
                }
536
        }
537
        else
538
        {
539
                return(0);
540
        }
541
}
542
 
543
//________________________________________________________________________________________________________________________________________
544
// Funtion:     GetNextCluster(File *file);
545
//
546
// Description: This function finds the next datacluster of the file specified with File *file.
547
//
548
// Returnvalue: The function returns "0" if the last cluster has already been reached.
549
//________________________________________________________________________________________________________________________________________
550
 
551
u16 GetNextCluster(File *file)
552
{
553
        u32 fat_pointer                 =       0;
554
        u32 fat_sector_offset   =       0;
555
        u32 ul_tmp                              =       0;
556
        u8 retvalue                             =       0;                                                                              // no new cluster found yet.
557
 
558
 
559
        if((file->cluster_pointer >= RootDirectory) && (file->cluster_pointer < (RootDirectory + 31)))
560
        {                                                                                                                                                               // Is the next cluster searched within the rootdirectory and available?
561
                file->cluster_pointer++;                                                                                                        // the rootdirectory is a linear adress space of 32 clusters.
562
                retvalue = 1;                                                                                                                           // and the next cluster has been found.
563
        }
564
        else if(file->cluster_pointer > (RootDirectory + 31))                                                   // The specified cluster is within the FAT.
565
        {
566
                fat_sector_offset   = ((file->cluster_pointer) - (FirstDataCluster));           // Calculate index of actual cluster within the FAT.
567
                fat_sector_offset  /= SectorsPerCluster;                                                                        // calculate the index of the actual sector within the FAT.
568
                fat_sector_offset  += 2;                                                                                                        // In Fat16 clusterpositions have an offset of two.
569
                fat_pointer = (fat_sector_offset%0x100);                                                                        // Calculate the sector within the cluster.
570
                fat_sector_offset   = (fat_sector_offset>>8);                                                           // and the position within the sector.
571
 
572
                SDC_GetSector((u32)(FileAllocationTable + fat_sector_offset),file->buffer);
573
                file->sector_in_buffer = (FileAllocationTable + fat_sector_offset);                     // Mark that new sector has been read.
574
 
575
                ul_tmp  = (u32)file->buffer[((fat_pointer << 1)+1)];                            // Read next sector information from calculated clusterposition.
576
                ul_tmp  = (ul_tmp << 8);
577
                ul_tmp |= (u32)file->buffer[(fat_pointer << 1)];
578
                ul_tmp -=2;                                                                                                                                     // next datacluster is clusterposition in fat - 2.
579
                ul_tmp *= SectorsPerCluster;                                                                                            // calculate sectorposition of new cluster
580
                ul_tmp += FirstDataCluster;                                                                                                     // in relation to first datacluster of the disk.
581
 
582
                if(ul_tmp < 0xfff7)                                                                                                                     // has a new cluster been read or was the end of the fat reached?
583
                {
584
                        file->cluster_pointer = (u32) ul_tmp;                                           // continue reading the file at the beginning of new datacluster.
585
                        retvalue = 1;                                                                                                                   // a new cluster was found.
586
                }
587
        }
588
        return(retvalue);
589
}
590
 
591
//________________________________________________________________________________________________________________________________________
592
// Funtion:     u16 FindNextFreeCluster(void)
593
//
594
// Description: This function looks in the FAT to find the next free datacluster
595
//
596
// Returnvalue: The function returns the adress of the next free cluster found within the fAT.
597
//________________________________________________________________________________________________________________________________________
598
 
599
u16 FindNextFreeCluster(File *file)
600
{
601
        u32 fat_pointer                 =       0;                                                      // Pointer to the first sector of the FAT.
602
        u32 ul_tmp                              =       0;                                                      // temporary variable used to calculate a sectornumber.
603
        u16  fat_sector_offset  =       0;                                                      // index to a sector within the FAT.
604
        u16  fat_entry                  =       0;                                                      // index to an fatentry within the actual sector (256 fatentries are possible within one sector).
605
        u16  free_cluster                       =       0;                                                      // a pointer to the first sector of the next free cluster.
606
 
607
        fat_pointer = (u32) FileAllocationTable;                                        // start searching for empty cluster at the beginning of the fat.
608
                                                                                                                                                // if the end of the fat is not reached yet and no free cluster has been found
609
        while((fat_sector_offset < SectorsPerFat) && (!free_cluster))
610
        {
611
                ul_tmp = (u32) ((u32)fat_pointer + (u32)fat_sector_offset);
612
                SDC_GetSector((u32)ul_tmp,file->buffer);                                // read next sector of FAT.
613
                file->sector_in_buffer = ul_tmp;                                                                // remember the number of the sector in FileBuffer.
614
                Fat = (struct FatEntry *)file->buffer;
615
                for(fat_entry=0;fat_entry<256;fat_entry++)                                              // look for an free cluster at all entries in this sector of the fat.
616
                {
617
                        if(Fat[fat_entry].next_cluster == 0x0000)                                       // empty cluster found!!
618
                        {
619
                                Fat[fat_entry].next_cluster = 0xffff;                                   // mark this fat-entry as used and save it to the device.
620
                                SDC_PutSector((u32)file->sector_in_buffer,file->buffer);
621
                                free_cluster  = fat_entry;                                                              // the relative position of the free cluster found in this sector of the FAT.
622
                                free_cluster += (fat_sector_offset << 8);                               // calculate the absolute position of the free cluster in the FAT;
623
                                fat_entry = 256;                                                                                // terminate the search for a free cluster in this sector.
624
                        }
625
                }
626
                fat_sector_offset++;
627
        }
628
return(free_cluster);
629
}
630
 
631
//________________________________________________________________________________________________________________________________________
632
// Funtion:     u16 AppendCluster(File *file);
633
//
634
// Description: This function finds the next free datacluster on the disk and appends it to the specified file.
635
//
636
// Returnvalue: This funktion returns 1 if a cluster was appended to the specified file.
637
//________________________________________________________________________________________________________________________________________
638
 
639
u8 AppendCluster(File *file)
640
{
641
        u16  free_cluster = 0;
642
        u32 fat_pointer = 0;
643
        u8 retvalue     = 0;
644
 
645
        free_cluster = FindNextFreeCluster(file);                                                                                               // the next free cluster found on the disk.
646
        if(free_cluster) retvalue = 1;                                                                                                                  // A free cluster was found and can be added to the end of the file.
647
        fat_pointer  = FileAllocationTable;                                                                                                             // Set Pointer to the beginnig of the FAT.
648
        fat_pointer += (u32)((u32)GetFatClusterOffset(file) >> 8);                                                              // find the sector in the FAT with 256 entries per sector.
649
 
650
    SDC_GetSector(fat_pointer,file->buffer);
651
        Fat = (struct FatEntry *)file->buffer;
652
        Fat[GetFatSectorIndex(file)].next_cluster = free_cluster;                                                               // append the free cluster to the end of the file in the FAT.
653
        SDC_PutSector((u32)fat_pointer,file->buffer);                                                                                   // save the modified sector to the FAT.
654
 
655
        fat_pointer  = (u32)free_cluster;
656
        fat_pointer -= 2;
657
        fat_pointer *= SectorsPerCluster;
658
        fat_pointer += FirstDataCluster;
659
 
660
        file->cluster_pointer = fat_pointer;                                                                                                    // continue wrtiting to the file in the new and free datacluster.
661
        return(retvalue);                                                                                                                                               // return 1 when a new cluster was appended to the file
662
}
663
 
664
 
665
//________________________________________________________________________________________________________________________________________
666
// Funtion:     void DeleteClusterChain(u16 startcluster);
667
//
668
// Description: This function frees all the clusters used for file from the fat.
669
//
670
// Returnvalue: none
671
//________________________________________________________________________________________________________________________________________
672
 
673
void DeleteClusterChain(u16 startcluster)
674
{
675
        u16 fat_index                   =       0;
676
        u16 fat_sector_offset   =       0;
677
        u32 sector_in_buffer    =       0;
678
        u32 ul_temp                             =       0;
679
        u8 buffer[512];
680
 
681
        fat_index = (startcluster % 0x100);                                                                                             // Calculate the sector within the cluster.
682
        fat_sector_offset = (startcluster >> 8);                                                                                        // and the position within the sector.
683
        ul_temp = (u32)(FileAllocationTable + fat_sector_offset);
684
 
685
 
686
        do
687
        {
688
                if(sector_in_buffer != ul_temp)
689
                {
690
                        sector_in_buffer = ul_temp;
691
                        SDC_GetSector(ul_temp,buffer);
692
                }
693
                Fat = (struct FatEntry *)buffer;
694
 
695
                startcluster = Fat[fat_index].next_cluster;
696
                Fat[fat_index].next_cluster = 0x0000;                                                                                   // free the cluster within the fat.
697
 
698
                fat_index = (startcluster % 0x100);                                                                                             // Calculate the sector within the cluster.
699
                fat_sector_offset = (startcluster >> 8);                                                                                        // and the position within the sector.
700
                ul_temp = (u32)(FileAllocationTable + fat_sector_offset);
701
                if((sector_in_buffer != ul_temp) || (startcluster == 0xffff))
702
                {
703
                        SDC_PutSector(sector_in_buffer,buffer);
704
                }
705
        }
706
        while(startcluster != 0xffff);                                                                                                                  // last cluster has been deleted.
707
}
708
 
709
 
710
//________________________________________________________________________________________________________________________________________
711
// Funtion:     u16 GetFatClusterIndex(File *file);
712
//
713
// Description: This function returns the clusterindex of the cluster specified by file->cluster_pointer of the specified file.
714
//
715
//________________________________________________________________________________________________________________________________________
716
 
717
u16 GetFatClusterOffset(File *file)
718
{
719
        u32 fat_sector_offset   =       0;
720
 
721
        fat_sector_offset   = ((file->cluster_pointer) - (FirstDataCluster));                           // Calculate index of actual cluster in FAT.
722
        fat_sector_offset  /= SectorsPerCluster;
723
        fat_sector_offset  += 2;                                                                                                                        // In Fat16 clusterpositions have an offset of two.
724
 
725
        return((u16)fat_sector_offset);
726
}
727
 
728
//________________________________________________________________________________________________________________________________________
729
// Funtion:     u16 GetFatSectorIndex(File *file);
730
//
731
// Description: This function returns the sectorindex of the cluster specified by file->cluster_pointer of the specified file.
732
//
733
//________________________________________________________________________________________________________________________________________
734
 
735
u16 GetFatSectorIndex(File *file)
736
{
737
        u16 fat_pointer                 =       0;
738
 
739
        fat_pointer = GetFatClusterOffset(file);
740
        fat_pointer = fat_pointer % 0x100;                                                                                                      // Calculate the clusterposition in the fat
741
 
742
        return(fat_pointer);
743
}
744
 
745
//________________________________________________________________________________________________________________________________________
746
// Funtion:     u16 CreateFileInDirectory(u8 *, File *)
747
//
748
// Description: This function looks for the next free position in the directory and creates an entry. The type of an directoryentry is
749
//                              specified by the attribute.
750
//                              bit0:   unused
751
//                              bit1:   archive
752
//                              bit2:   read_only
753
//                              bit3:   system
754
//                              bit4:   directory
755
//                              bit5:   volume
756
//________________________________________________________________________________________________________________________________________
757
 
758
u8 CreateFileInDirectory(s8 *fname, File *file)
759
{
760
        u16     rootentry       = 0;                                                                                                    // index to an entry in the rootdirectory.
761
        u16     cnt_enries_searched = 0;                                                                                        // count the number of rootentries which have been searched already.
762
        u8              i = 0;
763
        u16     sector_offset = 0;                                                                                                      // index to the sector of the Rootentry which is searched momentarily
764
        u8              retvalue = 0;
765
        u32             cluster_temp = 0;
766
        u16             cluster = 0;
767
        s8 name[11]     = "           ";
768
 
769
        SeperateFileName(fname,name);
770
 
771
        cluster_temp = (u32)FindNextFreeCluster(file);                                                          // the next free cluster on the disk.
772
 
773
        if(cluster_temp)                                                                                                                        // if a free cluster is available:
774
        {
775
                cluster = (u16)cluster_temp;                                                                                    // remember the index of the free datacluster found for the directory entry.
776
                cluster_temp -=2;                                                                                                               // Clusterposition is ((position in FAT)-2). first two entries in FAT are reserved.
777
                cluster_temp *= SectorsPerCluster;                                                                              // Calculate relative sectorindex of first datacluster.
778
                file->start_cluster   = (FirstDataCluster + cluster_temp);                              // Calculate absolute sectorposition of first datacluster.
779
                file->cluster_pointer = file->start_cluster;                                                    // start reading the file with the first sector of the first datacluster.
780
 
781
                                                                                                                                                                // directory starts at sector specified by dir_sector. This can be the rootdirectory or any other directory.
782
                do
783
                {                                                                                                                                                       // search the next 16 rootentries in this sector of the roordirectory.
784
                        rootentry=0;
785
                        SDC_GetSector((u32)(CWD + sector_offset),file->buffer); // Read the Rootdirectory.
786
                        DirectoryEntry = (struct DirEntry *)file->buffer;
787
                        while((rootentry<16) && (!retvalue))
788
                        {
789
                                if((DirectoryEntry[rootentry].attribute == 0) || (DirectoryEntry[rootentry].attribute == 0xE5)) // empty directory entry found
790
                                {
791
                                        for(i=0;i<11;i++) DirectoryEntry[rootentry].name[i] = name[i];          // Kopie the filename and the file extension to the directoryentry.
792
                                        DirectoryEntry[rootentry].attribute    = _FILE;                                         // Set the fileattribute to archive to reserve the directoryentry.
793
                                        DirectoryEntry[rootentry].startcluster = cluster;                                               // copy the location of the first datacluster to the directoryentry.
794
                                        DirectoryEntry[rootentry].size     = 0;                                                                 // the new createted file has no content yet.
795
                                        file->directory_sector = (u32) (CWD + sector_offset);
796
                                        file->directory_index  = (u8) rootentry;
797
                                        retvalue = 1;
798
                                        SDC_PutSector((u32)(CWD + sector_offset),file->buffer);
799
                                }
800
                                rootentry++;
801
                                cnt_enries_searched++;
802
                        }
803
                        if(!retvalue)                                                                                                                                   // file not found in this sector so take next sector.
804
                        {
805
                                rootentry = 0;
806
                                sector_offset++;
807
                        }
808
                }
809
                while((cnt_enries_searched< PossibleRootEntries) && (!retvalue));
810
 
811
        }
812
        return(retvalue);                                                                                                                                       // return 1 if file has been created otherwise return 0.
813
}
814
 
815
//________________________________________________________________________________________________________________________________________
816
// Funtion:     u16 SeekFileInDirectory(s8 *fname, File *)
817
//
818
// Description: this function searches all possible entries withint the actual directory for the specified object.
819
//
820
// Returnvalue: This function returns 1 if the directoryentry specified was found.
821
//________________________________________________________________________________________________________________________________________
822
 
823
u8 SeekFileInDirectory(s8 *fname, File *file)
824
{
825
        u16     rootentry=0;
826
        u16     end_of_directory_not_reached = 0;                                                                       // the directory has been read completely without a result.
827
        u8              i=0;
828
        u8      retvalue = 0;
829
        u32     cluster_temp = 0;
830
        s8 name[11]     = "           ";
831
 
832
        SeperateFileName(fname,name);
833
 
834
        file->cluster_pointer = CWD;                                                                                            // start looking for the file in the actual directory.
835
 
836
                                                                                                                                                                // directory starts at sector specified by dir_sector. This can be the rootdirectory or any other directory.
837
        do
838
        {                                                                                                                                                       // search the next 16 rootentries in this sector of the roordirectory.
839
                rootentry=0;
840
                SDC_GetSector((u32) file->cluster_pointer,file->buffer);                                        // Read the Rootdirectory.
841
                DirectoryEntry = (struct DirEntry *)file->buffer;
842
 
843
                while((!retvalue)&&(rootentry<16))
844
                {
845
                        i=0;
846
                        if(DirectoryEntry[rootentry].name[0] != 0xe5)                                                   // ignore deleted items.
847
                        {
848
                                while((i<=10)&&(DirectoryEntry[rootentry].name[i] == name[i]))
849
                                {
850
                                        i++;
851
                                }
852
                        }
853
 
854
                        if((i==11) && (DirectoryEntry[rootentry].attribute & _FILE))            // entry found!! -> reading startcluster of entry from offset 26.
855
                        {
856
                                cluster_temp = (u32)DirectoryEntry[rootentry].startcluster;
857
                                cluster_temp -=2;                                                                                                                       // Clusterposition is ((position in FAT)-2). first two entries in FAT are reserved.
858
                                cluster_temp *= (u32)SectorsPerCluster;                                                 // Calculate positon of first cluster.
859
                                file->start_cluster   = (FirstDataCluster + cluster_temp);
860
                                file->directory_sector = (u32) file->cluster_pointer;
861
                                file->cluster_pointer = file->start_cluster;                                                            // start reading the file with the first cluster.
862
                                file->filesize = (u32) DirectoryEntry[rootentry].size;
863
                                file->directory_index  = (u8) rootentry;
864
                                retvalue = 1;
865
                        }
866
                        rootentry++;
867
                }
868
                if(!retvalue)                                                                                   // file not found in this sector so take next sector.
869
                {
870
                        end_of_directory_not_reached = GetNextCluster(file);
871
                }
872
        }
873
        while((end_of_directory_not_reached) && (!retvalue));
874
        return(retvalue);
875
}
876
 
877
 
878
 
879
//________________________________________________________________________________________________________________________________________
880
// Funtion:     void SeperateFileName(u8*);
881
//
882
// Description: This function seperates the filename and the fileattribute and brings them into the needed format ('test.txt' -> 'TEST    TXT');
883
//
884
//________________________________________________________________________________________________________________________________________
885
 
886
void SeperateFileName(s8 *fname, s8 *name)
887
{
888
        u8 readpointer  = 0;
889
        u8 writepointer = 0;
890
        u8 attribute    = 1;
891
        u8 i = 0;
892
 
893
 
894
        while((writepointer<=10) && (fname[readpointer]!=0))    // the rootdirectoryentry is 8bytes for filename and 3bytes for fileattribute.
895
        {                                                                                                               // the filename in the rootdirectory is in the format "TEST    TXT" without the dot.
896
                if(fname[readpointer]=='.')                                             // seperating filename and attribute.
897
                {
898
                        if(attribute)                                                                   // is the filename "." or ".." ?
899
                        {
900
                                name[writepointer] = fname[readpointer];
901
                                readpointer++;
902
                                writepointer++;
903
                        }
904
                        else
905
                        {
906
                                if(fname[(readpointer-1)] != '*')
907
                                {
908
                                        for(i=writepointer;i<8;i++)
909
                                        {
910
                                                name[i] = ' ';
911
                                        }
912
                                }
913
                                readpointer++;
914
                                writepointer = 8;
915
                        }
916
                }
917
                else if(fname[readpointer] == '*')                                      // wildcard found within the filename + extension.
918
                {
919
                        if(writepointer < 8)                                            // in extension.
920
                        {
921
                                readpointer++;
922
                                writepointer = 8;
923
                        }
924
                        else                                                                            // in filename.
925
                        {
926
                                writepointer = 11;                                              // jump to the end of the string to terminate this function.
927
                        }
928
                        attribute = 0;
929
                }
930
                else
931
                {
932
                        if((fname[readpointer]>96) && (fname[readpointer]<123))
933
                        {
934
                                name[writepointer]=(fname[readpointer] - 32);                                   // all characters must be upper case.
935
                        }
936
                        else
937
                        {
938
                                name[writepointer]=fname[readpointer];
939
                        }
940
                        readpointer++;
941
                        writepointer++;
942
                        attribute = 0;
943
                }
944
        }
945
}
946
 
947
//________________________________________________________________________________________________________________________________________
948
// Funtion:     File * ReserveFilePointer_(void);
949
//
950
// Description: This function looks for a free filepointer and reserves it.
951
//
952
//
953
//      Return:         NULL = faild to reserve a filepointer
954
//                              otherwise filepointer
955
//________________________________________________________________________________________________________________________________________
956
 
957
File * ReserveFilePointer(void)
958
{
959
        File *file;
960
        file = NULL;
961
        u8      temp;
962
 
963
        for(temp = 0;temp<__MAX_FILES_USED;temp++)
964
        {
965
                if(FilePointer[temp].state == _UNUSED)                                                                          // free filepointer found?
966
                {
967
                        file = &FilePointer[temp];
968
                        FilePointer[temp].state                                 = _USED;                                                // mark as used.
969
                        FilePointer[temp].mode                                  = 0;                                                    // type of access (read/write) not defined yet.
970
                        FilePointer[temp].start_cluster                 = 0;                                                    // Sectorpointer to the first sector of the first datacluster of the file.
971
                        FilePointer[temp].cluster_pointer               = 0;                                                    // Pointer to the cluster which is edited at the moment.
972
                        FilePointer[temp].sector_index                  = 0;                                                    // The sector which is edited at the moment (cluster_pointer + sector_index).
973
                        FilePointer[temp].byte_index                    = 0;                                                    // The bytelocation within the current sector (cluster_pointer + sector_index + byte_index).
974
                        FilePointer[temp].filesize                              = 0;                                                    // the size of the opend file in bytes.
975
                        FilePointer[temp].fileposition                  = 0;                                                    // pointer to a character within the file 0 < fileposition < filesize
976
                        FilePointer[temp].sector_in_buffer              = 0;                                                    // the last sector read, wich is still in the sectorbuffer.
977
                        FilePointer[temp].directory_sector              = 0;                                                    // the sectorposition where the directoryentry has been made.
978
                        FilePointer[temp].directory_index               = 0;                                                    // the index to the directoryentry within the specified sector.
979
                        FilePointer[temp].attribute                     = 0;                                                    // the attribute of the file opened.
980
                        break;
981
                }
982
        }
983
        return(file);
984
}
985
 
986
 
987
//________________________________________________________________________________________________________________________________________
988
// Funtion:     void FreeFilePointer_(File *);
989
//
990
// Description: This function free's the filepointer by marking it as unused.
991
//
992
//
993
//      Return:         none
994
//
995
//________________________________________________________________________________________________________________________________________
996
 
997
void FreeFilePointer(File *file)
998
{
999
        u8 cnt = 0;
1000
 
1001
        for(cnt=0;cnt<__MAX_FILES_USED;cnt++)                                                                                   // Is the filepointeradress vaild?
1002
        {
1003
                if(&FilePointer[cnt] == file)                                                                                           // filepointer found therefore it must be valid
1004
                {
1005
                        FilePointer[cnt].state = _UNUSED;                                                                               // and can be marked as unused.
1006
                }
1007
        }
1008
}
1009
 
1010
 
1011
//________________________________________________________________________________________________________________________________________
1012
// Funtion:     void DelteDirectoryEntry(Find *)
1013
//
1014
// Description: This function deletes the directoryentry of the specified item.
1015
//
1016
//
1017
// returnvalue: 1 if the directory could be created.
1018
//________________________________________________________________________________________________________________________________________
1019
 
1020
void DeleteDirectoryEntry(Find *item)
1021
{
1022
        u8 buffer[512];
1023
 
1024
 
1025
        SDC_GetSector((u32) item->cluster_pointer,buffer);                                                              // Read the Rootdirectory.
1026
        DirectoryEntry = (struct DirEntry *)buffer;
1027
 
1028
        DirectoryEntry[(item->directory_index)-1].attribute = 0;                                                        // free the directoryentry.
1029
        DirectoryEntry[(item->directory_index)-1].name[0] = 0xE5;                                                       // free the directoryentry.
1030
        SDC_PutSector((u32) item->cluster_pointer,buffer);                                                              // Read the Rootdirectory.
1031
}
1032
 
1033
 
1034
 
1035
 
1036
//________________________________________________________________________________________________________________________________________
1037
// Funtion:     u8 CreateSubDirectory(u8 *)
1038
//
1039
// Description: This function creates an directory within the directory specified by CWD
1040
//
1041
//
1042
// returnvalue: 1 if the directory could be created.
1043
//________________________________________________________________________________________________________________________________________
1044
 
1045
u8 CreateSubDirectory(s8 *fname)
1046
{
1047
        u16     index   = 0;                                                                                                                            // index to an entry in the rootdirectory.
1048
        u16     cnt_entries_searched = 0;                                                                                                               // count the number of rootentries which have been searched already.
1049
        u16             i = 0;
1050
        u16     sector_offset = 0;                                                                                                                              // index to the sector of the entry which is searched momentarily
1051
        u8              retvalue = 0;
1052
        u32             cluster_temp = 0;
1053
        u16             cluster = 0;
1054
        File    file;
1055
        u8              name[11] = {"           "};
1056
 
1057
        SeperateFileName(fname,name);
1058
        cluster_temp = (u32)FindNextFreeCluster(&file);                                                                         // the next free cluster on the disk.
1059
 
1060
        if(cluster_temp)                                                                                                                                                // if a free cluster is available:
1061
        {
1062
                cluster = (u16)cluster_temp;                                                                                                            // remember the index of the free datacluster found for the directory entry.
1063
                cluster_temp -=2;                                                                                                                                       // Clusterposition is ((position in FAT)-2). first two entries in FAT are reserved.
1064
                cluster_temp *= SectorsPerCluster;                                                                                                      // Calculate relative sectorindex of first datacluster.
1065
                file.start_cluster   = (FirstDataCluster + cluster_temp);                                                       // Calculate absolute sectorposition of first datacluster.
1066
                file.cluster_pointer = file.start_cluster;                                                                                      // start reading the file with the first sector of the first datacluster.
1067
 
1068
// -Initialise new cluster to zero--------------------------------------------------------
1069
                for(i=0;i<512;i++)
1070
                {
1071
                        file.buffer[i] = 0;                                                                                                                             // initialise buffer to zero
1072
                }
1073
                for(sector_offset=0;sector_offset<SectorsPerCluster;sector_offset++)                            // initialise all sectors of new cluster with buffer.
1074
                {
1075
                        SDC_PutSector((u32)(file.start_cluster + sector_offset),file.buffer);                   // save the initialised sector to the card.
1076
                }
1077
// -Create directoryentry "." -------------------------------------------------------------
1078
                DirectoryEntry = (struct DirEntry *)file.buffer;
1079
                DirectoryEntry[0].name[0] = '.';
1080
                DirectoryEntry[0].attribute = _DIRECTORY;
1081
                DirectoryEntry[0].startcluster = cluster;
1082
// -Create directoryentry "." -------------------------------------------------------------
1083
                DirectoryEntry[1].name[0] = '.';
1084
                DirectoryEntry[1].name[1] = '.';
1085
                DirectoryEntry[1].attribute = _DIRECTORY;
1086
                if(CWD == RootDirectory)
1087
                {
1088
                        DirectoryEntry[1].startcluster = 0;
1089
                }
1090
                else
1091
                {
1092
                        cluster_temp = (CWD - FirstDataCluster);
1093
                        cluster_temp /= SectorsPerCluster;
1094
                        cluster_temp -= 2;
1095
                        DirectoryEntry[1].startcluster = (u16) cluster_temp;
1096
                }
1097
                SDC_PutSector((u32) file.start_cluster,file.buffer);                                                                                    // save the initialised sector to the card.
1098
// -create directoryentry within the cwd --------------------------------------------------
1099
                sector_offset = 0;
1100
                cnt_entries_searched = 0;
1101
                do
1102
                {                                                                                                                                                                       // search the next 16 rootentries in this sector of the roordirectory.
1103
                        index=0;
1104
                        SDC_GetSector((u32)(CWD + sector_offset),file.buffer);                                                  // Read the actual directory.
1105
                        DirectoryEntry = (struct DirEntry *)file.buffer;
1106
                        while((index<16) && (!retvalue))
1107
                        {
1108
                                if((DirectoryEntry[index].attribute == 0) || (DirectoryEntry[index].attribute == 0xE5)) // empty directory entry found
1109
                                {
1110
                                        for(i=0;i<11;i++) DirectoryEntry[index].name[i] = name[i];              // Kopie the filename and the file extension to the directoryentry.
1111
                                        DirectoryEntry[index].attribute    = _DIRECTORY;                                        // Set the fileattribute to archive to reserve the directoryentry.
1112
                                        DirectoryEntry[index].startcluster = cluster;                                           // copy the location of the first datacluster to the directoryentry.
1113
                                        DirectoryEntry[index].size     = 0;                                                                     // the new createted file has no content yet.
1114
                                        file.directory_sector = (u32) (CWD + sector_offset);
1115
                                        file.directory_index  = (u8) index;
1116
                                        retvalue = 1;
1117
                                        SDC_PutSector((u32)(CWD + sector_offset),file.buffer);
1118
                                }
1119
                                index++;
1120
                                cnt_entries_searched++;
1121
                        }
1122
                        if(!retvalue)                                                                                                                                   // file not found in this sector so take next sector.
1123
                        {
1124
                                index = 0;
1125
                                sector_offset++;
1126
                        }
1127
                }
1128
                while((cnt_entries_searched< PossibleRootEntries) && (!retvalue));
1129
 
1130
        }
1131
        return(retvalue);                                                                                                                                       // return 1 if file has been created otherwise return 0.
1132
}
1133
 
1134
 
1135
//________________________________________________________________________________________________________________________________________
1136
// Funtion:     u16 SeekSubDirectory(s8 *fname)
1137
//
1138
// Description: looks for the specified directory within the CWD.
1139
//
1140
// Returnvalue: If the specified directory was found the startcluster is returned. otherwise 0.
1141
//________________________________________________________________________________________________________________________________________
1142
 
1143
u16 SeekSubDirectory(s8 *fname)
1144
{
1145
        u16     index = 0;
1146
        u16     end_of_directory_not_reached = 0;                                                                       // the directory has been read completely without a result.
1147
        u8              i = 0;
1148
        u16     cluster_temp = 0;
1149
        s8 name[11]     = "           ";
1150
        File    file;
1151
 
1152
        SeperateFileName(fname,name);
1153
 
1154
        file.cluster_pointer = CWD;                                                                                                     // start looking for the file in the actual directory.
1155
        file.start_cluster   = CWD;                                                                                                     // start looking for the file in the actual directory.
1156
 
1157
                                                                                                                                                                // directory starts at sector specified by dir_sector. This can be the rootdirectory or any other directory.
1158
        do
1159
        {                                                                                                                                                       // search the next 16 rootentries in this sector of the roordirectory.
1160
                index=0;
1161
                SDC_GetSector((u32) file.cluster_pointer,file.buffer);                                  // Read the Rootdirectory.
1162
                DirectoryEntry = (struct DirEntry *)file.buffer;
1163
 
1164
                while((!cluster_temp)&&(index<16))
1165
                {
1166
                        i=0;
1167
                        if(DirectoryEntry[index].name[0] != 0xe5)                                                       // ignore deleted items.
1168
                        {
1169
                                while((i<=10)&&(DirectoryEntry[index].name[i] == name[i]))
1170
                                {
1171
                                        i++;
1172
                                }
1173
                        }
1174
 
1175
                        if((i==11) && (DirectoryEntry[index].attribute & _DIRECTORY))   // entry found!! -> reading startcluster of entry from offset 26.
1176
                        {
1177
                                cluster_temp = (u16)DirectoryEntry[index].startcluster;
1178
                        }
1179
                        index++;
1180
                }
1181
                if(!cluster_temp)                                                                                       // file not found in this sector so take next sector.
1182
                {
1183
                        end_of_directory_not_reached = GetNextCluster(&file);
1184
                }
1185
        }
1186
        while((end_of_directory_not_reached) && (!cluster_temp));
1187
        return(cluster_temp);
1188
}
1189
 
1190
 
1191
 
1192
//________________________________________________________________________________________________________________________________________
1193
// Funtion:     u8 mkdir_(u8 *)
1194
//
1195
// Description: This function checks if the directory to be created already exists. If not the directory will be created.
1196
//
1197
//
1198
// returnvalue: 1 if the directory could be created.
1199
//________________________________________________________________________________________________________________________________________
1200
 
1201
u8      mkdir_(s8 *fname)
1202
{
1203
        u8 retvalue = 0;
1204
 
1205
        retvalue = SeekSubDirectory(fname);                                                                                     // check wether the specified directory already exists.
1206
 
1207
        if(!retvalue)
1208
        {
1209
                CreateSubDirectory(fname);                                                                                              // if directory doesn't exist, create it.
1210
                retvalue = 1;
1211
        }
1212
        else
1213
        {
1214
                retvalue = 0;
1215
        }
1216
 
1217
        return(retvalue);
1218
}
1219
 
1220
 
1221
//________________________________________________________________________________________________________________________________________
1222
// Funtion:     u8 chdir_(u8 *)
1223
//
1224
// Description: This function changes the CWD to the directory specified.
1225
//
1226
//
1227
// returnvalue: 1 if the directory could be changed.
1228
//________________________________________________________________________________________________________________________________________
1229
 
1230
u8      chdir_(s8 *fname)
1231
{
1232
        u8      retvalue = 0;
1233
        u8  name[11] = {"           "};
1234
 
1235
        u32 ultemp = 0;
1236
 
1237
        SeperateFileName(fname,name);
1238
 
1239
        ultemp = (u32)SeekSubDirectory(name);
1240
        if(ultemp >= 2)
1241
        {
1242
                ultemp -=2;                                                                                                                                             // Clusterposition is ((position in FAT)-2). first two entries in FAT are reserved.
1243
                ultemp *= SectorsPerCluster;                                                                                                    // Calculate relative sectorindex of first datacluster.
1244
                ultemp += FirstDataCluster;
1245
                CWD = ultemp;
1246
                retvalue = 1;
1247
        }
1248
        else
1249
        {
1250
                CWD = RootDirectory;
1251
                retvalue = 1;
1252
        }
1253
 
1254
        return(retvalue);
1255
}
1256
 
1257
 
1258
//________________________________________________________________________________________________________________________________________
1259
// Funtion:     u8 FindItem(s8 *fname, Find *)
1260
//
1261
// Description: finds an item (file or directory) within common working directory (cwd). Wildcards '*' or '?' will be considered.
1262
//
1263
// Returnvalue: If an item was found this function returns '1' else '0'.
1264
//________________________________________________________________________________________________________________________________________
1265
 
1266
u8 FindItem(Find *item)
1267
{
1268
        u16     index = 0;
1269
        u16     end_of_directory_not_reached = 0;                                                                       // the directory has been read completely without a result.
1270
        u8              i = 0;
1271
        u8              readpointer = 0;
1272
        u8              writepointer = 0;
1273
        u8              retvalue = 0;
1274
        File    file;
1275
 
1276
 
1277
        file.cluster_pointer = item->cluster_pointer;
1278
        file.start_cluster   = item->cluster_pointer;
1279
        index                            = item->directory_index;
1280
                                                                                                                                                                // directory starts at sector specified by dir_sector. This can be the rootdirectory or any other directory.
1281
        do
1282
        {                                                                                                                                                       // search the next 16 rootentries in this sector of the roordirectory.
1283
                SDC_GetSector((u32) file.cluster_pointer,file.buffer);                                  // Read the Rootdirectory.
1284
                DirectoryEntry = (struct DirEntry *)file.buffer;
1285
 
1286
                while((!retvalue)&&(index<16))
1287
                {
1288
                        i=0;
1289
                        if(DirectoryEntry[index].name[0] != 0xe5)                                                       // ignore deleted items.
1290
                        {
1291
                                while((i<=10)&&((DirectoryEntry[index].name[i] == item->searchstring[i]) || (item->searchstring[i]=='*') || item->searchstring[i]=='?'))
1292
                                {
1293
                                        i++;
1294
                                }
1295
                        }
1296
 
1297
                        if((i==11) && (DirectoryEntry[index].attribute & item->attribute))
1298
                        {
1299
                                for(readpointer=0;readpointer<=10;readpointer++)
1300
                                {
1301
                                        if(DirectoryEntry[index].name[readpointer] != ' ')
1302
                                        {
1303
                                                item->name[writepointer] = DirectoryEntry[index].name[readpointer];     // copy the name of the item found to the find_structure.
1304
                                                writepointer++;
1305
                                        }
1306
                                        else if((readpointer==7) && (DirectoryEntry[index].attribute == _FILE)) // if the item found is a file
1307
                                        {
1308
                                                if(DirectoryEntry[index].name[readpointer] != ' ')
1309
                                                {
1310
                                                        item->name[writepointer] = DirectoryEntry[index].name[readpointer];     // copy the name of the item found to the find_structure.
1311
                                                        writepointer++;
1312
                                                }
1313
                                                item->name[writepointer] = '.';                                         // then seperate the name and the extension by a '.' at index 8.
1314
                                                writepointer++;
1315
                                        }
1316
                                }
1317
                                item->startcluster = (u16)DirectoryEntry[index].startcluster;
1318
                                item->directory_index = ++index;
1319
                                item->cluster_pointer = file.cluster_pointer;
1320
                                retvalue = 1;
1321
                        }
1322
                        index++;
1323
                }
1324
                if(!retvalue)                                                                                                                   // file not found in this sector so take next sector.
1325
                {
1326
                        end_of_directory_not_reached = GetNextCluster(&file);
1327
                }
1328
                index = 0;
1329
        }
1330
        while((end_of_directory_not_reached) && (!retvalue));
1331
 
1332
        return(retvalue);
1333
}
1334
 
1335
 
1336
//________________________________________________________________________________________________________________________________________
1337
// Funtion:     u8 findfirst(s8 *fname, Find *)
1338
//
1339
// Description: finds the first item (file or directory) within common working directory (cwd). Wildcards '*' or '?' will be considered.
1340
//
1341
// Returnvalue: If an item was found this function returns '1' else '0'.
1342
//________________________________________________________________________________________________________________________________________
1343
 
1344
u8 findfirst_(s8 *fname, Find *item, u8 attribute)
1345
{
1346
        u8 retvalue = 0;
1347
        u8 i = 0;
1348
 
1349
        for(i=0;i<=11;i++)
1350
        {
1351
                item->searchstring[i] = '*';                                                                                            // initialise the searchstring with wildcards.
1352
                item->name[i] = 0;
1353
        }
1354
 
1355
        SeperateFileName(fname,item->searchstring);
1356
 
1357
        item->cluster_pointer = CWD;                                                                                                    // findfirst_ starts at the beginning of the cwd.
1358
        item->directory_index = 0;
1359
        item->attribute = attribute;
1360
 
1361
        retvalue = FindItem(item);
1362
 
1363
        return(retvalue);
1364
}
1365
 
1366
 
1367
//________________________________________________________________________________________________________________________________________
1368
// Funtion:     u8 findnext(Find *)
1369
//
1370
// Description: finds the first item (file or directory) within common working directory (cwd). Wildcards '*' or '?' will be considered.
1371
//
1372
// Returnvalue: If an item was found this function returns '1' else '0'.
1373
//________________________________________________________________________________________________________________________________________
1374
 
1375
 
1376
u8 findnext_(Find *item)
1377
{
1378
        u8 retvalue = 0;
1379
        u8 i = 0;
1380
 
1381
        for(i=0;i<=11;i++)
1382
        {
1383
                item->name[i] = 0;
1384
        }
1385
 
1386
        retvalue = FindItem(item);
1387
 
1388
        return(retvalue);
1389
}
1390
 
1391
 
1392
 
1393
//________________________________________________________________________________________________________________________________________
1394
// Funtion:     u8 fdelete(s8 *fname)
1395
//
1396
// Description: Deletes the file specified by fname.
1397
//
1398
// Returnvalue:
1399
//________________________________________________________________________________________________________________________________________
1400
 
1401
 
1402
u8 fdelete_(s8 *fname)
1403
{
1404
        u8 retvalue = 0;
1405
        Find item;
1406
 
1407
        printf("\n\rDeleting file");
1408
        retvalue = findfirst_(fname,&item, _FILE);                                                                              // look for the item to be deleted.
1409
 
1410
        if(retvalue);                                                                                                                           // item found?
1411
        {
1412
                printf("\n\r");
1413
                printf("%s", item.name);
1414
 
1415
                DeleteClusterChain(item.startcluster);                                                                  // delete all fatentries of the item.
1416
                DeleteDirectoryEntry(&item);                                                                                    // free the directoryentry.
1417
 
1418
                do
1419
                {
1420
                        printf("\n\r");
1421
                        printf("%s", item.name);
1422
                        retvalue = findnext_(&item);
1423
                        if(retvalue)
1424
                        {
1425
                                DeleteClusterChain(item.startcluster);                                                                  // delete all fatentries of the item.
1426
                                DeleteDirectoryEntry(&item);                                                                                    // free the directoryentry.
1427
                        }
1428
                }
1429
                while(retvalue);
1430
        }
1431
 
1432
        printf("\n\rDone");
1433
 
1434
        return(retvalue);
1435
}
1436
 
1437
 
1438
 
1439
//________________________________________________________________________________________________________________________________________
1440
// Funtion:     u8 rmdir(s8 *fname)
1441
//
1442
// Description: Deletes the directory specified by dname.
1443
//
1444
// Returnvalue:
1445
//________________________________________________________________________________________________________________________________________
1446
 
1447
 
1448
u8 rmdir_(s8 *dname)
1449
{
1450
        u8 retvalue = 0;
1451
        Find item;
1452
 
1453
        printf("\n\rDeleting folder");
1454
        retvalue = findfirst_(dname,&item, _DIRECTORY);                                                                         // look for the item to be deleted.
1455
 
1456
        if(retvalue);                                                                                                                                           // item found?
1457
        {
1458
                printf("\n\r");
1459
                printf("%s", item.name);
1460
 
1461
                DeleteClusterChain(item.startcluster);                                                                                  // delete all fatentries of the item.
1462
                DeleteDirectoryEntry(&item);                                                                                                    // free the directoryentry.
1463
 
1464
                do
1465
                {
1466
                        printf("\n\r");
1467
                        printf("%s", item.name);
1468
                        retvalue = findnext_(&item);
1469
                        if(retvalue)
1470
                        {
1471
                                DeleteClusterChain(item.startcluster);                                                                  // delete all fatentries of the item.
1472
                                DeleteDirectoryEntry(&item);                                                                                    // free the directoryentry.
1473
                        }
1474
                }
1475
                while(retvalue);
1476
        }
1477
 
1478
        printf("\n\rDone");
1479
 
1480
        return(retvalue);
1481
}
1482