Subversion Repositories Projects

Rev

Rev 317 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 317 Rev 318
1
#include <string.h>
1
#include <string.h>
2
#include "printf_P.h"
2
#include "printf_P.h"
3
#include "timer0.h"
3
#include "timer0.h"
4
#include "fat16.h"
4
#include "fat16.h"
5
#include "sdc.h"
5
#include "sdc.h"
6
#include "uart1.h"
6
#include "uart1.h"
7
 
7
 
8
 
8
 
9
/*
9
/*
10
FAT16 Drive Layout:
10
FAT16 Drive Layout:
11
Description                                             Offset
11
Description                                             Offset
12
Volume Boot Sector                                      Start of Partition
12
Volume Boot Sector                                      Start of Partition
13
Fat Tables                                                      Start + # of Reserved Sectors
13
Fat Tables                                                      Start + # of Reserved Sectors
14
Root Directory Entry                            Start + # of Reserved + (# of Sectors Per FAT * 2)
14
Root Directory Entry                            Start + # of Reserved + (# of Sectors Per FAT * 2)
15
Data Area (Starts with Cluster #2)      Start + # of Reserved + (# of Sectors Per FAT * 2) + ((Maximum Root Directory Entries * 32) / Bytes per Sector)
15
Data Area (Starts with Cluster #2)      Start + # of Reserved + (# of Sectors Per FAT * 2) + ((Maximum Root Directory Entries * 32) / Bytes per Sector)
16
*/
16
*/
17
 
17
 
18
 
18
 
19
/*
19
/*
20
________________________________________________________________________________________________________________________________________
20
________________________________________________________________________________________________________________________________________
21
 
21
 
22
        Structure of an partition entry
22
        Structure of an partition entry
23
________________________________________________________________________________________________________________________________________
23
________________________________________________________________________________________________________________________________________
24
 
24
 
25
        Partition Entry is 16 bytes long
25
        Partition Entry is 16 bytes long
26
*/
26
*/
27
typedef struct
27
typedef struct
28
{
28
{
29
        uint8_t         PartitionState;                         // Current State of Partition (00h=Inactive, 80h=Active)
29
        uint8_t         PartitionState;                         // Current State of Partition (00h=Inactive, 80h=Active)
30
        uint8_t         BeginningHead;                          // Beginning of Partition - Head
30
        uint8_t         BeginningHead;                          // Beginning of Partition - Head
31
        uint16_t        BeginningCylSec;                        // Beginning of Partition - Cylinder/Sector (See Below)
31
        uint16_t        BeginningCylSec;                        // Beginning of Partition - Cylinder/Sector (See Below)
32
        uint8_t         Type;                                           // Type of Partition (See List Below)
32
        uint8_t         Type;                                           // Type of Partition (See List Below)
33
        uint8_t         EndHead;                                        // End of Partition - Head
33
        uint8_t         EndHead;                                        // End of Partition - Head
34
        uint16_t        EndCylSec;                                      // End of Partition - Cylinder/Sector
34
        uint16_t        EndCylSec;                                      // End of Partition - Cylinder/Sector
35
        uint32_t        NoSectorsBeforePartition;       // Number of Sectors between the MBR and the First Sector in the Partition
35
        uint32_t        NoSectorsBeforePartition;       // Number of Sectors between the MBR and the First Sector in the Partition
36
        uint32_t        NoSectorsPartition      ;               // Number of Sectors in the Partition
36
        uint32_t        NoSectorsPartition      ;               // Number of Sectors in the Partition
37
} __attribute__((packed)) PartitionEntry_t;
37
} __attribute__((packed)) PartitionEntry_t;
38
 
38
 
39
/*
39
/*
40
Coding of Cylinder/Sector words
40
Coding of Cylinder/Sector words
41
 
41
 
42
Cylinder is 10 bits:  [7:0] at [15:8] and [9:8] at [7:6]
42
Cylinder is 10 bits:  [7:0] at [15:8] and [9:8] at [7:6]
43
Sector is 5 bits:  [5:0] at [5:0]
43
Sector is 5 bits:  [5:0] at [5:0]
44
*/
44
*/
45
 
45
 
46
// Partition Types:
46
// Partition Types:
47
#define PART_TYPE_UNKNOWN                       0x00
47
#define PART_TYPE_UNKNOWN                       0x00
48
#define PART_TYPE_FAT12                         0x01
48
#define PART_TYPE_FAT12                         0x01
49
#define PART_TYPE_XENIX                         0x02
49
#define PART_TYPE_XENIX                         0x02
50
#define PART_TYPE_FAT16_ST_32_MB        0x04
50
#define PART_TYPE_FAT16_ST_32_MB        0x04
51
#define PART_TYPE_EXTDOS                        0x05
51
#define PART_TYPE_EXTDOS                        0x05
52
#define PART_TYPE_FAT16_LT_32_MB        0x06
52
#define PART_TYPE_FAT16_LT_32_MB        0x06
53
#define PART_TYPE_NTFS                          0x07
53
#define PART_TYPE_NTFS                          0x07
54
#define PART_TYPE_FAT32                         0x0B
54
#define PART_TYPE_FAT32                         0x0B
55
#define PART_TYPE_FAT32LBA                      0x0C
55
#define PART_TYPE_FAT32LBA                      0x0C
56
#define PART_TYPE_FAT16LBA                      0x0E
56
#define PART_TYPE_FAT16LBA                      0x0E
57
#define PART_TYPE_EXTDOSLBA                     0x0F
57
#define PART_TYPE_EXTDOSLBA                     0x0F
58
#define PART_TYPE_EISA                          0x12
58
#define PART_TYPE_EISA                          0x12
59
#define PART_TYPE_ONTRACK                       0x33
59
#define PART_TYPE_ONTRACK                       0x33
60
#define PART_TYPE_NOVELL                        0x40
60
#define PART_TYPE_NOVELL                        0x40
61
#define PART_TYPE_DYNAMIC                       0x42
61
#define PART_TYPE_DYNAMIC                       0x42
62
#define PART_TYPE_PCIX                          0x4B
62
#define PART_TYPE_PCIX                          0x4B
63
#define PART_TYPE_LINUX_SWAP            0x82
63
#define PART_TYPE_LINUX_SWAP            0x82
64
#define PART_TYPE_LINUX_NATIVE          0x83
64
#define PART_TYPE_LINUX_NATIVE          0x83
65
#define PART_TYPE_LINUX_LVM                     0x8E
65
#define PART_TYPE_LINUX_LVM                     0x8E
66
#define PART_TYPE_PHOENIXSAVE           0xA0
66
#define PART_TYPE_PHOENIXSAVE           0xA0
67
#define PART_TYPE_FREEBSD                       0xA5
67
#define PART_TYPE_FREEBSD                       0xA5
68
#define PART_TYPE_OPENBSD                       0xA6
68
#define PART_TYPE_OPENBSD                       0xA6
69
#define PART_TYPE_NETNBSD                       0xA9
69
#define PART_TYPE_NETNBSD                       0xA9
70
#define PART_TYPE_CPM                           0xDB
70
#define PART_TYPE_CPM                           0xDB
71
#define PART_TYPE_DBFS                          0xE0
71
#define PART_TYPE_DBFS                          0xE0
72
#define PART_TYPE_BBT                           0xFF
72
#define PART_TYPE_BBT                           0xFF
73
 
73
 
74
 
74
 
75
/*
75
/*
76
________________________________________________________________________________________________________________________________________
76
________________________________________________________________________________________________________________________________________
77
 
77
 
78
        Structure of the MasterBootRecord
78
        Structure of the MasterBootRecord
79
________________________________________________________________________________________________________________________________________
79
________________________________________________________________________________________________________________________________________
80
 
80
 
81
        Master Boot Record is 512 bytes long
81
        Master Boot Record is 512 bytes long
82
        The Master Boot Record is the same for pretty much all Operating Systems.
82
        The Master Boot Record is the same for pretty much all Operating Systems.
83
        It is located on the first Sector of the Hard Drive, at Cylinder 0, Head 0, Sector 1
83
        It is located on the first Sector of the Hard Drive, at Cylinder 0, Head 0, Sector 1
84
*/
84
*/
85
typedef struct
85
typedef struct
86
{
86
{
87
        uint8_t                         ExecutableCode[446];    // 446 bytes for machine start code
87
        uint8_t                         ExecutableCode[446];    // 446 bytes for machine start code
88
        PartitionEntry_t        PartitionEntry1;                // 16 bytes for partition entry 1
88
        PartitionEntry_t        PartitionEntry1;                // 16 bytes for partition entry 1
89
        PartitionEntry_t        PartitionEntry2;                // 16 bytes for partition entry 2
89
        PartitionEntry_t        PartitionEntry2;                // 16 bytes for partition entry 2
90
        PartitionEntry_t        PartitionEntry3;                // 16 bytes for partition entry 3
90
        PartitionEntry_t        PartitionEntry3;                // 16 bytes for partition entry 3
91
        PartitionEntry_t        PartitionEntry4;                // 16 bytes for partition entry 4
91
        PartitionEntry_t        PartitionEntry4;                // 16 bytes for partition entry 4
92
        uint16_t                        ExecutableMarker;               // BIOS-Signature (0x55 0xAA)
92
        uint16_t                        ExecutableMarker;               // BIOS-Signature (0x55 0xAA)
93
} __attribute__((packed)) MBR_Entry_t;
93
} __attribute__((packed)) MBR_Entry_t;
94
 
94
 
95
 
95
 
96
/*
96
/*
97
________________________________________________________________________________________________________________________________________
97
________________________________________________________________________________________________________________________________________
98
 
98
 
99
        Structure of the VolumeBootRecord
99
        Structure of the VolumeBootRecord
100
________________________________________________________________________________________________________________________________________
100
________________________________________________________________________________________________________________________________________
101
 
101
 
102
        The Volume Boot Record is 512 bytes long
102
        The Volume Boot Record is 512 bytes long
103
        This information is located in the first sector of every partition.
103
        This information is located in the first sector of every partition.
104
*/
104
*/
105
typedef struct
105
typedef struct
106
{
106
{
107
        uint8_t         JumpCode[3];                    // Jump Code + NOP
107
        uint8_t         JumpCode[3];                    // Jump Code + NOP
108
        int8_t          OEMName[8];                             // OEM Name
108
        int8_t          OEMName[8];                             // OEM Name
109
        uint16_t        BytesPerSector;                 // Bytes Per Sector
109
        uint16_t        BytesPerSector;                 // Bytes Per Sector
110
        uint8_t         SectorsPerCluster;              // Sectors Per Cluster
110
        uint8_t         SectorsPerCluster;              // Sectors Per Cluster
111
        uint16_t        ReservedSectors;                // Reserved Sectors
111
        uint16_t        ReservedSectors;                // Reserved Sectors
112
        uint8_t         NoFATCopies;                    // Number of Copies of FAT
112
        uint8_t         NoFATCopies;                    // Number of Copies of FAT
113
        uint16_t        MaxRootEntries;                 // Maximum Root Directory Entries
113
        uint16_t        MaxRootEntries;                 // Maximum Root Directory Entries
114
        uint16_t        NoSectorsInPartSml32MB; // Number of Sectors in Partition Smaller than 32 MB
114
        uint16_t        NoSectorsInPartSml32MB; // Number of Sectors in Partition Smaller than 32 MB
115
        uint8_t         MediaDescriptor;                // Media Descriptor (0xF8 for Hard Disks)
115
        uint8_t         MediaDescriptor;                // Media Descriptor (0xF8 for Hard Disks)
116
        uint16_t        SectorsPerFAT;                  // Sectors Per FAT
116
        uint16_t        SectorsPerFAT;                  // Sectors Per FAT
117
        uint16_t        SectorsPerTrack;                // Sectors Per Track
117
        uint16_t        SectorsPerTrack;                // Sectors Per Track
118
        uint16_t        NoHeads;                                // Number of Heads
118
        uint16_t        NoHeads;                                // Number of Heads
119
        uint32_t        NoHiddenSectors;                // Number of Hidden Sectors     in Partition
119
        uint32_t        NoHiddenSectors;                // Number of Hidden Sectors     in Partition
120
        uint32_t        NoSectors;                              // Number of Sectors in Partition
120
        uint32_t        NoSectors;                              // Number of Sectors in Partition
121
        uint16_t        DriveNo;                                // Logical Drive Number of Partition
121
        uint16_t        DriveNo;                                // Logical Drive Number of Partition
122
        uint8_t         ExtendedSig;                    // Extended Signature (0x29)
122
        uint8_t         ExtendedSig;                    // Extended Signature (0x29)
123
        uint32_t        SerialNo;                               // Serial Number of the Partition
123
        uint32_t        SerialNo;                               // Serial Number of the Partition
124
        int8_t          VolumeName[11];                 // Volume Name of the Partititon
124
        int8_t          VolumeName[11];                 // Volume Name of the Partititon
125
        int8_t          FATName[8];                             // FAT Name (FAT16)
125
        int8_t          FATName[8];                             // FAT Name (FAT16)
126
        uint8_t         ExecutableCode[446];    // 446 bytes for machine start code
126
        uint8_t         ExecutableCode[446];    // 446 bytes for machine start code
127
        uint16_t        ExecutableMarker;               // Executable Marker (0x55 0xAA)
127
        uint16_t        ExecutableMarker;               // Executable Marker (0x55 0xAA)
128
} __attribute__((packed)) VBR_Entry_t;
128
} __attribute__((packed)) VBR_Entry_t;
129
 
129
 
130
 
130
 
131
 
131
 
132
/*
132
/*
133
________________________________________________________________________________________________________________________________________
133
________________________________________________________________________________________________________________________________________
134
 
134
 
135
        Structure of an directory entry
135
        Structure of an directory entry
136
________________________________________________________________________________________________________________________________________
136
________________________________________________________________________________________________________________________________________
137
 
137
 
138
        Directory entry is 32 bytes.
138
        Directory entry is 32 bytes.
139
*/
139
*/
140
typedef struct
140
typedef struct
141
{
141
{
142
        int8_t          Name[8];                                        // 8 bytes name, padded with spaces.
142
        int8_t          Name[8];                                        // 8 bytes name, padded with spaces.
143
        uint8_t         Extension[3];                           // 3 bytes extension, padded with spaces.
143
        uint8_t         Extension[3];                           // 3 bytes extension, padded with spaces.
144
        uint8_t         Attribute;                                      // attribute of the directory entry (unused,archive,read-only,system,directory,volume)
144
        uint8_t         Attribute;                                      // attribute of the directory entry (unused,archive,read-only,system,directory,volume)
145
        uint8_t         Reserved[10];                           // reserved bytes within the directory entry.
145
        uint8_t         Reserved[10];                           // reserved bytes within the directory entry.
146
        uint32_t        DateTime;                                       // date and time of last write access to the file or directory.
146
        uint32_t        DateTime;                                       // date and time of last write access to the file or directory.
147
        uint16_t        StartCluster;                           // first cluster of the file or directory.
147
        uint16_t        StartCluster;                           // first cluster of the file or directory.
148
        uint32_t        Size;                                           // size of the file or directory in bytes.
148
        uint32_t        Size;                                           // size of the file or directory in bytes.
149
}  __attribute__((packed)) DirEntry_t;
149
}  __attribute__((packed)) DirEntry_t;
150
 
150
 
151
#define SLOT_EMPTY              0x00    // slot has never been used
151
#define SLOT_EMPTY              0x00    // slot has never been used
152
#define SLOT_E5                 0x05    // the real value is 0xe5
152
#define SLOT_E5                 0x05    // the real value is 0xe5
153
#define SLOT_DELETED            0xE5    // file in this slot deleted
153
#define SLOT_DELETED            0xE5    // file in this slot deleted
154
 
154
 
155
#define ATTR_NONE               0x00    // normal file
155
#define ATTR_NONE               0x00    // normal file
156
#define ATTR_READONLY           0x01    // file is readonly
156
#define ATTR_READONLY           0x01    // file is readonly
157
#define ATTR_HIDDEN                     0x02    // file is hidden
157
#define ATTR_HIDDEN                     0x02    // file is hidden
158
#define ATTR_SYSTEM                     0x04    // file is a system file
158
#define ATTR_SYSTEM                     0x04    // file is a system file
159
#define ATTR_VOLUMELABEL        0x08    // entry is a volume label
159
#define ATTR_VOLUMELABEL        0x08    // entry is a volume label
160
#define ATTR_LONG_FILENAME      0x0F    // this is a long filename entry
160
#define ATTR_LONG_FILENAME      0x0F    // this is a long filename entry
161
#define ATTR_SUBDIRECTORY       0x10    // entry is a directory name
161
#define ATTR_SUBDIRECTORY       0x10    // entry is a directory name
162
#define ATTR_ARCHIVE            0x20    // file is new or modified
162
#define ATTR_ARCHIVE            0x20    // file is new or modified
163
 
163
 
164
 
164
 
165
/*
165
/*
166
________________________________________________________________________________________________________________________________________
166
________________________________________________________________________________________________________________________________________
167
 
167
 
168
        Structure of an entry within the fileallocationtable.
168
        Structure of an entry within the fileallocationtable.
169
________________________________________________________________________________________________________________________________________
169
________________________________________________________________________________________________________________________________________
170
*/
170
*/
171
typedef struct
171
typedef struct
172
{
172
{
173
        uint16_t  NextCluster;                          // the next cluster of the file.
173
        uint16_t  NextCluster;                          // the next cluster of the file.
174
} __attribute__((packed)) Fat16Entry_t;
174
} __attribute__((packed)) Fat16Entry_t;
175
 
175
 
176
// secial fat entries
176
// secial fat entries
177
#define FAT16_CLUSTER_FREE                      0x0000
177
#define FAT16_CLUSTER_FREE                      0x0000
178
#define FAT16_CLUSTER_RESERVED          0x0001
178
#define FAT16_CLUSTER_RESERVED          0x0001
179
#define FAT16_CLUSTER_USED_MIN          0x0002
179
#define FAT16_CLUSTER_USED_MIN          0x0002
180
#define FAT16_CLUSTER_USED_MAX          0xFFEF
180
#define FAT16_CLUSTER_USED_MAX          0xFFEF
181
#define FAT16_CLUSTER_ROOTDIR_MIN       0xFFF0
181
#define FAT16_CLUSTER_ROOTDIR_MIN       0xFFF0
182
#define FAT16_CLUSTER_ROOTDIR_MAX       0xFFF6
182
#define FAT16_CLUSTER_ROOTDIR_MAX       0xFFF6
183
#define FAT16_CLUSTER_BAD                       0xFFF7
183
#define FAT16_CLUSTER_BAD                       0xFFF7
184
#define FAT16_CLUSTER_LAST_MIN          0xFFF8
184
#define FAT16_CLUSTER_LAST_MIN          0xFFF8
185
#define FAT16_CLUSTER_LAST_MAX          0xFFFF
185
#define FAT16_CLUSTER_LAST_MAX          0xFFFF
186
 
186
 
187
/*****************************************************************************************************************************************/
187
/*****************************************************************************************************************************************/
188
/*                                                                                                                                                                                                                                                                               */
188
/*                                                                                                                                                                                                                                                                               */
189
/*      Global variables needed for read- or write-acces to the FAT16- filesystem.                                                                                                                       */
189
/*      Global variables needed for read- or write-acces to the FAT16- filesystem.                                                                                                                       */
190
/*                                                                                                                                                                                                                                                                               */
190
/*                                                                                                                                                                                                                                                                               */
191
/*****************************************************************************************************************************************/
191
/*****************************************************************************************************************************************/
192
 
192
 
193
#define MBR_SECTOR                                      0x00    // the masterboot record is located in sector 0.
193
#define MBR_SECTOR                                      0x00    // the masterboot record is located in sector 0.
194
#define DIRENTRY_SIZE                           32              //bytes
194
#define DIRENTRY_SIZE                           32              //bytes
195
#define DIRENTRIES_PER_SECTOR           BYTES_PER_SECTOR/DIRENTRY_SIZE
195
#define DIRENTRIES_PER_SECTOR           BYTES_PER_SECTOR/DIRENTRY_SIZE
196
#define FAT16_BYTES                                     2
196
#define FAT16_BYTES                                     2
197
#define FAT16_ENTRIES_PER_SECTOR        BYTES_PER_SECTOR/FAT16_BYTES
197
#define FAT16_ENTRIES_PER_SECTOR        BYTES_PER_SECTOR/FAT16_BYTES
198
 
198
 
199
#define FSTATE_UNUSED   0
199
#define FSTATE_UNUSED   0
200
#define FSTATE_USED             1
200
#define FSTATE_USED             1
201
 
201
 
202
typedef struct
202
typedef struct
203
{
203
{
204
        uint8_t         IsValid;                                // 0 means invalid, else valid
204
        uint8_t         IsValid;                                // 0 means invalid, else valid
205
        uint8_t         SectorsPerCluster;              // how many sectors does a cluster contain?
205
        uint8_t         SectorsPerCluster;              // how many sectors does a cluster contain?
206
        uint8_t         FatCopies;                              // Numbers of copies of the FAT
206
        uint8_t         FatCopies;                              // Numbers of copies of the FAT
207
        uint16_t        MaxRootEntries;                 // Possible number of entries in the root directory.
207
        uint16_t        MaxRootEntries;                 // Possible number of entries in the root directory.
208
        uint16_t        SectorsPerFat;                  // how many sectors does a fat16 contain?
208
        uint16_t        SectorsPerFat;                  // how many sectors does a fat16 contain?
209
        uint32_t        FirstFatSector;                 // sector of the start of the fat
209
        uint32_t        FirstFatSector;                 // sector of the start of the fat
210
        uint32_t        FirstRootDirSector;             // sector of the rootdirectory
210
        uint32_t        FirstRootDirSector;             // sector of the rootdirectory
211
        uint32_t        FirstDataSector;                // sector of the first cluster containing data (cluster2).
211
        uint32_t        FirstDataSector;                // sector of the first cluster containing data (cluster2).
212
        uint32_t        LastDataSector;                 // the last data sector of the partition
212
        uint32_t        LastDataSector;                 // the last data sector of the partition
213
} Partition_t;
213
} Partition_t;
214
 
214
 
215
Partition_t     Partition;                                      // Structure holds partition information
215
Partition_t     Partition;                                      // Structure holds partition information
216
 
216
 
217
File_t FilePointer[FILE_MAX_OPEN];      // Allocate Memmoryspace for each filepointer used.
217
File_t FilePointer[FILE_MAX_OPEN];      // Allocate Memmoryspace for each filepointer used.
218
 
218
 
219
 
219
 
220
/****************************************************************************************************************************************/
220
/****************************************************************************************************************************************/
221
/*      Function:               FileDateTime(DateTime_t *);                                                                                                                                                                                     */
221
/*      Function:               FileDateTime(DateTime_t *);                                                                                                                                                                                     */
222
/*                                                                                                                                                                                                                                                                              */
222
/*                                                                                                                                                                                                                                                                              */
223
/*      Description:    This function calculates the DOS date time from a pointer to a time structure.                                                                          */
223
/*      Description:    This function calculates the DOS date time from a pointer to a time structure.                                                                          */
224
/*                                                                                                                                                                                                                                                                              */
224
/*                                                                                                                                                                                                                                                                              */
225
/*      Returnvalue:    Returns the DOS date time.                                                                                                                                                                                      */
225
/*      Returnvalue:    Returns the DOS date time.                                                                                                                                                                                      */
226
/****************************************************************************************************************************************/
226
/****************************************************************************************************************************************/
227
 
227
 
228
uint32_t FileDateTime(DateTime_t * pTimeStruct)
228
uint32_t FileDateTime(DateTime_t * pTimeStruct)
229
{
229
{
230
        uint32_t datetime = 0;
230
        uint32_t datetime = 0;
231
        if((pTimeStruct == 0) || !(pTimeStruct->Valid)) return datetime;
231
        if((pTimeStruct == 0) || !(pTimeStruct->Valid)) return datetime;
232
 
232
 
233
        datetime |= (0x0000007FL & (uint32_t)(pTimeStruct->Year - 1980))<<25; // set year
233
        datetime |= (0x0000007FL & (uint32_t)(pTimeStruct->Year - 1980))<<25; // set year
234
        datetime |= (0x0000000FL & (uint32_t)(pTimeStruct->Month))<<21; // set month
234
        datetime |= (0x0000000FL & (uint32_t)(pTimeStruct->Month))<<21; // set month
235
        datetime |= (0x0000001FL & (uint32_t)(pTimeStruct->Day))<<16;
235
        datetime |= (0x0000001FL & (uint32_t)(pTimeStruct->Day))<<16;
236
        datetime |= (0x0000001FL & (uint32_t)(pTimeStruct->Hour))<<11;
236
        datetime |= (0x0000001FL & (uint32_t)(pTimeStruct->Hour))<<11;
237
        datetime |= (0x0000003FL & (uint32_t)(pTimeStruct->Min))<<5;
237
        datetime |= (0x0000003FL & (uint32_t)(pTimeStruct->Min))<<5;
238
        datetime |= (0x0000001FL & (uint32_t)(pTimeStruct->Sec/2));
238
        datetime |= (0x0000001FL & (uint32_t)(pTimeStruct->Sec/2));
239
        return datetime;
239
        return datetime;
240
}
240
}
241
 
241
 
242
 
242
 
243
/****************************************************************************************************************************************/
243
/****************************************************************************************************************************************/
244
/*      Function:               LockFilePointer();                                                                                                                                                                                                      */
244
/*      Function:               LockFilePointer();                                                                                                                                                                                                      */
245
/*                                                                                                                                                                                                                                                                              */
245
/*                                                                                                                                                                                                                                                                              */
246
/*      Description:    This function trys to lock a free file pointer.                                                                                                                                         */
246
/*      Description:    This function trys to lock a free file pointer.                                                                                                                                         */
247
/*                                                                                                                                                                                                                                                                              */
247
/*                                                                                                                                                                                                                                                                              */
248
/*      Returnvalue:    Returns the Filepointer on success or 0.                                                                                                                                                        */
248
/*      Returnvalue:    Returns the Filepointer on success or 0.                                                                                                                                                        */
249
/****************************************************************************************************************************************/
249
/****************************************************************************************************************************************/
250
File_t * LockFilePointer(void)
250
File_t * LockFilePointer(void)
251
{
251
{
252
        uint8_t i;
252
        uint8_t i;
253
        File_t * File = 0;
253
        File_t * File = 0;
254
        for(i = 0; i < FILE_MAX_OPEN; i++)
254
        for(i = 0; i < FILE_MAX_OPEN; i++)
255
        {
255
        {
256
                if(FilePointer[i].State == FSTATE_UNUSED)               // found an unused one
256
                if(FilePointer[i].State == FSTATE_UNUSED)               // found an unused one
257
                {
257
                {
258
                        File = &FilePointer[i];                                         // set pointer to that entry
258
                        File = &FilePointer[i];                                         // set pointer to that entry
259
                        FilePointer[i].State = FSTATE_USED;                     // mark it as used
259
                        FilePointer[i].State = FSTATE_USED;                     // mark it as used
260
                        break;
260
                        break;
261
                }
261
                }
262
        }
262
        }
263
        return(File);
263
        return(File);
264
}
264
}
265
 
265
 
266
/****************************************************************************************************************************************/
266
/****************************************************************************************************************************************/
267
/*      Function:               UnlockFilePointer(file_t *);                                                                                                                                                                            */
267
/*      Function:               UnlockFilePointer(file_t *);                                                                                                                                                                            */
268
/*                                                                                                                                                                                                                                                                              */
268
/*                                                                                                                                                                                                                                                                              */
269
/*      Description:    This function trys to unlock a file pointer.                                                                                                                                            */
269
/*      Description:    This function trys to unlock a file pointer.                                                                                                                                            */
270
/*                                                                                                                                                                                                                                                                              */
270
/*                                                                                                                                                                                                                                                                              */
271
/*      Returnvalue:    Returns 1 if file pointer was freed else 0.                                                                                                                                                     */
271
/*      Returnvalue:    Returns 1 if file pointer was freed else 0.                                                                                                                                                     */
272
/****************************************************************************************************************************************/
272
/****************************************************************************************************************************************/
273
uint8_t UnlockFilePointer(File_t * file)
273
uint8_t UnlockFilePointer(File_t * file)
274
{
274
{
275
        uint8_t cnt;
275
        uint8_t cnt;
276
        if(file == NULL) return(0);
276
        if(file == NULL) return(0);
277
        for(cnt = 0; cnt < FILE_MAX_OPEN; cnt++)
277
        for(cnt = 0; cnt < FILE_MAX_OPEN; cnt++)
278
        {
278
        {
279
                if(&FilePointer[cnt] == file)                                           // filepointer to be freed found?
279
                if(&FilePointer[cnt] == file)                                           // filepointer to be freed found?
280
                {
280
                {
281
                        file->State = FSTATE_UNUSED;
281
                        file->State = FSTATE_UNUSED;
282
                        file->FirstSectorOfFirstCluster = 0;                    // Sectorpointer to the first sector of the first datacluster of the file.
282
                        file->FirstSectorOfFirstCluster = 0;                    // Sectorpointer to the first sector of the first datacluster of the file.
283
                        file->FirstSectorOfCurrCluster  = 0;
283
                        file->FirstSectorOfCurrCluster  = 0;
284
                        file->SectorOfCurrCluster               = 0;                    // Pointer to the cluster which is edited at the moment.
284
                        file->SectorOfCurrCluster               = 0;                    // Pointer to the cluster which is edited at the moment.
285
                        file->SectorOfCurrCluster               = 0;                    // The sector which is edited at the moment (cluster_pointer + sector_index).
285
                        file->SectorOfCurrCluster               = 0;                    // The sector which is edited at the moment (cluster_pointer + sector_index).
286
                        file->ByteOfCurrSector                  = 0;                    // The bytelocation within the current sector (cluster_pointer + sector_index + byte_index).
286
                        file->ByteOfCurrSector                  = 0;                    // The bytelocation within the current sector (cluster_pointer + sector_index + byte_index).
287
                        file->Mode                                              = 0;                    // mode of fileoperation (read,write)
287
                        file->Mode                                              = 0;                    // mode of fileoperation (read,write)
288
                        file->Size                                              = 0;                    // the size of the opend file in bytes.
288
                        file->Size                                              = 0;                    // the size of the opend file in bytes.
289
                        file->Position                                  = 0;                    // pointer to a character within the file 0 < fileposition < filesize
289
                        file->Position                                  = 0;                    // pointer to a character within the file 0 < fileposition < filesize
290
                        file->SectorInCache                     = 0;                    // the last sector read, wich is still in the sectorbuffer.
290
                        file->SectorInCache                     = 0;                    // the last sector read, wich is still in the sectorbuffer.
291
                        file->DirectorySector                   = 0;                    // the sectorposition where the directoryentry has been made.
291
                        file->DirectorySector                   = 0;                    // the sectorposition where the directoryentry has been made.
292
                        file->DirectoryIndex                    = 0;                    // the index to the directoryentry within the specified sector.
292
                        file->DirectoryIndex                    = 0;                    // the index to the directoryentry within the specified sector.
293
                        file->Attribute                                 = 0;                    // the attribute of the file opened.
293
                        file->Attribute                                 = 0;                    // the attribute of the file opened.
294
                        file = NULL;
294
                        file = NULL;
295
                        return(1);
295
                        return(1);
296
                }
296
                }
297
        }
297
        }
298
        return(0);
298
        return(0);
299
}
299
}
300
 
300
 
301
/****************************************************************************************************************************************/
301
/****************************************************************************************************************************************/
302
/*      Function:               SeperateDirName(int8_t*, int8_t*);                                                                                                                                                                              */
302
/*      Function:               SeperateDirName(int8_t*, int8_t*);                                                                                                                                                                              */
303
/*                                                                                                                                                                                                                                                                              */
303
/*                                                                                                                                                                                                                                                                              */
304
/*      Description:    This function seperates the first dirname from filepath and brings them                                                                                         */
304
/*      Description:    This function seperates the first dirname from filepath and brings them                                                                                         */
305
/*                                      into the needed format ('test.txt' -> 'TEST    TXT')                                                                                                                            */
305
/*                                      into the needed format ('test.txt' -> 'TEST    TXT')                                                                                                                            */
306
/*                                      The subpath is the pointer to the remaining substring if the filepath                                                                                           */
306
/*                                      The subpath is the pointer to the remaining substring if the filepath                                                                                           */
307
/*                                                                                                                                                                                                                                                                              */
307
/*                                                                                                                                                                                                                                                                              */
308
/*      Returnvalue:    Return NULL on error or pointer to subpath                                                                                                                                                                                                      */
308
/*      Returnvalue:    Return NULL on error or pointer to subpath                                                                                                                                                                                                      */
309
/****************************************************************************************************************************************/
309
/****************************************************************************************************************************************/
310
int8_t* SeperateDirName(const int8_t *filepath, int8_t *dirname)
310
int8_t* SeperateDirName(const int8_t *filepath, int8_t *dirname)
311
{
311
{
312
        int8_t* subpath = NULL;
312
        int8_t* subpath = NULL;
313
        uint8_t readpointer     = 0;
313
        uint8_t readpointer     = 0;
314
        uint8_t writepointer = 0;
314
        uint8_t writepointer = 0;
315
 
315
 
316
        // search subpath from beginning of filepath
316
        // search subpath from beginning of filepath
317
        subpath = NULL;
317
        subpath = NULL;
318
        readpointer     = 0;
318
        readpointer     = 0;
319
        if(filepath[0] == '/') readpointer = 1; // ignore first '/'
319
        if(filepath[0] == '/') readpointer = 1; // ignore first '/'
320
        while(subpath == NULL)  // search the filepath until a subpath was found.
320
        while(subpath == NULL)  // search the filepath until a subpath was found.
321
        {
321
        {
322
                if(((filepath[readpointer] == 0) || (filepath[readpointer] == '/')))    // if '/' found or end of filepath reached
322
                if(((filepath[readpointer] == 0) || (filepath[readpointer] == '/')))    // if '/' found or end of filepath reached
323
                {
323
                {
324
                        subpath = (int8_t*)&filepath[readpointer];                              // store the position of the first "/" found after the beginning of the filenpath
324
                        subpath = (int8_t*)&filepath[readpointer];                              // store the position of the first "/" found after the beginning of the filenpath
325
                }
325
                }
326
                readpointer++;
326
                readpointer++;
327
        }
327
        }
328
 
328
 
329
        // clear dirname with spaces
329
        // clear dirname with spaces
330
        dirname[11] = 0; // terminate dirname
330
        dirname[11] = 0; // terminate dirname
331
        for(writepointer = 0; writepointer < 11; writepointer++) dirname[writepointer] = ' ';
331
        for(writepointer = 0; writepointer < 11; writepointer++) dirname[writepointer] = ' ';
332
        writepointer = 0;
332
        writepointer = 0;
333
        // start seperating the dirname from the filepath.
333
        // start seperating the dirname from the filepath.
334
        readpointer = 0;
334
        readpointer = 0;
335
        if(filepath[0] == '/') readpointer = 1; // ignore first '/'
335
        if(filepath[0] == '/') readpointer = 1; // ignore first '/'
336
        while( &filepath[readpointer] < subpath)
336
        while( &filepath[readpointer] < subpath)
337
        {
337
        {
338
                if(writepointer >= 11) return(NULL);            // dirname to long
338
                if(writepointer >= 11) return(NULL);            // dirname to long
339
                if(filepath[readpointer] == '.')                        // seperating dirname and extension.
339
                if(filepath[readpointer] == '.')                        // seperating dirname and extension.
340
                {
340
                {
341
                        if(writepointer <= 8)
341
                        if(writepointer <= 8)
342
                        {
342
                        {
343
                                readpointer++;                                          // next character in filename
343
                                readpointer++;                                          // next character in filename
344
                                writepointer = 8;                                       // jump to start of extension
344
                                writepointer = 8;                                       // jump to start of extension
345
                        }
345
                        }
346
                        else return(NULL);                                              // dirbasename to long
346
                        else return(NULL);                                              // dirbasename to long
347
                }
347
                }
348
                else
348
                else
349
                {
349
                {
350
                        if((0x60 < filepath[readpointer]) && (filepath[readpointer] < 0x7B))
350
                        if((0x60 < filepath[readpointer]) && (filepath[readpointer] < 0x7B))
351
                        {
351
                        {
352
                                dirname[writepointer] = (filepath[readpointer] - 0x20);                                 // all characters must be upper case.
352
                                dirname[writepointer] = (filepath[readpointer] - 0x20);                                 // all characters must be upper case.
353
                        }
353
                        }
354
                        else
354
                        else
355
                        {
355
                        {
356
                                dirname[writepointer] = filepath[readpointer];
356
                                dirname[writepointer] = filepath[readpointer];
357
                        }
357
                        }
358
                        readpointer++;
358
                        readpointer++;
359
                        writepointer++;
359
                        writepointer++;
360
                }
360
                }
361
        }
361
        }
362
        return(subpath);
362
        return(subpath);
363
}
363
}
364
 
364
 
365
 
365
 
366
/**************************************************************************************************************************************+*/
366
/**************************************************************************************************************************************+*/
367
/*      Function:       Fat16ClusterToSector( uint16_t cluster);                                                                                                                                                                                */
367
/*      Function:       Fat16ClusterToSector( uint16_t cluster);                                                                                                                                                                                */
368
/*                                                                                                                                                                                                                                                                              */
368
/*                                                                                                                                                                                                                                                                              */
369
/*      Description:    This function converts a cluster number given by the fat to the corresponding                                                                           */
369
/*      Description:    This function converts a cluster number given by the fat to the corresponding                                                                           */
370
/*                                      sector that points to the start of the data area that is represented by the cluster number.                                                     */
370
/*                                      sector that points to the start of the data area that is represented by the cluster number.                                                     */
371
/*                                                                                                                                                                                                                                                                              */
371
/*                                                                                                                                                                                                                                                                              */
372
/*      Returnvalue: The sector number with the data area of the given cluster                                                                                                                          */
372
/*      Returnvalue: The sector number with the data area of the given cluster                                                                                                                          */
373
/****************************************************************************************************************************************/
373
/****************************************************************************************************************************************/
374
uint32_t        Fat16ClusterToSector(uint16_t cluster)
374
uint32_t        Fat16ClusterToSector(uint16_t cluster)
375
{
375
{
376
        if(!Partition.IsValid) return 0;
376
        if(!Partition.IsValid) return 0;
377
        if (cluster < 2) cluster = 2; // the 0. and 1. cluster in the fat are used for the media descriptor
377
        if (cluster < 2) cluster = 2; // the 0. and 1. cluster in the fat are used for the media descriptor
378
        return ( (cluster - 2) * Partition.SectorsPerCluster) + Partition.FirstDataSector; // the first data sector     is represented by the 2nd cluster
378
        return ( (cluster - 2) * Partition.SectorsPerCluster) + Partition.FirstDataSector; // the first data sector     is represented by the 2nd cluster
379
}
379
}
380
 
380
 
381
/****************************************************************************************************************************************/
381
/****************************************************************************************************************************************/
382
/*      Function:       SectorToFat16Cluster( uint32_t sector);                                                                                                                                                                         */
382
/*      Function:       SectorToFat16Cluster( uint32_t sector);                                                                                                                                                                         */
383
/*                                                                                                                                                                                                                                                                              */
383
/*                                                                                                                                                                                                                                                                              */
384
/*      Description:    This function converts a given sector number given to the corresponding                                                                                         */
384
/*      Description:    This function converts a given sector number given to the corresponding                                                                                         */
385
/*                                      cluster number in the fat that represents this data area.                                                                                                                       */
385
/*                                      cluster number in the fat that represents this data area.                                                                                                                       */
386
/*                                                                                                                                                                                                                                                                              */
386
/*                                                                                                                                                                                                                                                                              */
387
/*      Returnvalue: The cluster number representing the data area of the sector.                                                                                                                       */
387
/*      Returnvalue: The cluster number representing the data area of the sector.                                                                                                                       */
388
/****************************************************************************************************************************************/
388
/****************************************************************************************************************************************/
389
uint16_t        SectorToFat16Cluster(uint32_t sector)
389
uint16_t        SectorToFat16Cluster(uint32_t sector)
390
{
390
{
391
        if(!Partition.IsValid) return 0;
391
        if(!Partition.IsValid) return 0;
392
        return ((uint16_t)((sector - Partition.FirstDataSector) / Partition.SectorsPerCluster) + 2);
392
        return ((uint16_t)((sector - Partition.FirstDataSector) / Partition.SectorsPerCluster) + 2);
393
}
393
}
394
 
394
 
395
 
395
 
396
/****************************************************************************************************************************************/
396
/****************************************************************************************************************************************/
397
/*      Function:       Fat16_Deinit(void);                                                                                                                                                                                                             */
397
/*      Function:       Fat16_Deinit(void);                                                                                                                                                                                                             */
398
/*                                                                                                                                                                                                                                                                              */
398
/*                                                                                                                                                                                                                                                                              */
399
/*      Description:    This function uninitializes the fat 16 api                                                                                                                                                      */
399
/*      Description:    This function uninitializes the fat 16 api                                                                                                                                                      */
400
/*                                                                                                                                                                                                                                                                              */
400
/*                                                                                                                                                                                                                                                                              */
401
/*      Returnvalue: The function returns "0" on success                                                                                                                                                                        */
401
/*      Returnvalue: The function returns "0" on success                                                                                                                                                                        */
402
/****************************************************************************************************************************************/
402
/****************************************************************************************************************************************/
403
uint8_t Fat16_Deinit(void)
403
uint8_t Fat16_Deinit(void)
404
{
404
{
405
        int16_t returnvalue = 0;
405
        int16_t returnvalue = 0;
406
        uint8_t cnt;
406
        uint8_t cnt;
407
        // declare the filepointers as unused.
407
        // declare the filepointers as unused.
408
        for(cnt = 0; cnt < FILE_MAX_OPEN; cnt++)
408
        for(cnt = 0; cnt < FILE_MAX_OPEN; cnt++)
409
        {
409
        {
410
                if(FilePointer[cnt].State == FSTATE_USED)
410
                if(FilePointer[cnt].State == FSTATE_USED)
411
                {
411
                {
412
                        returnvalue += fclose_(&FilePointer[cnt]); // try to close open file pointers
412
                        returnvalue += fclose_(&FilePointer[cnt]); // try to close open file pointers
413
                }
413
                }
414
 
414
 
415
        }
415
        }
416
        SDC_Deinit();                   // uninitialize interface to sd-card
416
        SDC_Deinit();                   // uninitialize interface to sd-card
417
        Partition.IsValid = 0;  // mark data in partition structure as invalid
417
        Partition.IsValid = 0;  // mark data in partition structure as invalid
418
        return(returnvalue);
418
        return(returnvalue);
419
}
419
}
420
 
420
 
421
/****************************************************************************************************************************************/
421
/****************************************************************************************************************************************/
422
/*      Function:               Fat16_Init(void);                                                                                                                                                                                                       */
422
/*      Function:               Fat16_Init(void);                                                                                                                                                                                                       */
423
/*                                                                                                                                                                                                                                                                          */
423
/*                                                                                                                                                                                                                                                                          */
424
/*      Description:    This function reads the Masterbootrecord and finds the position of the Volumebootrecord, the FAT and the Rootdir    */
424
/*      Description:    This function reads the Masterbootrecord and finds the position of the Volumebootrecord, the FAT and the Rootdir    */
425
/*                                      and stores the information in global variables.                                                                                                                                     */
425
/*                                      and stores the information in global variables.                                                                                                                                     */
426
/*                                                                                                                                                                                                                                                                          */
426
/*                                                                                                                                                                                                                                                                          */
427
/*      Returnvalue:    The function returns "0" if the filesystem is initialized.                                                                                                                      */
427
/*      Returnvalue:    The function returns "0" if the filesystem is initialized.                                                                                                                      */
428
/****************************************************************************************************************************************/
428
/****************************************************************************************************************************************/
429
uint8_t Fat16_Init(void)
429
uint8_t Fat16_Init(void)
430
{
430
{
431
    uint8_t     cnt     = 0;
431
    uint8_t     cnt     = 0;
432
        uint32_t        partitionfirstsector;
432
        uint32_t        partitionfirstsector;
433
        VBR_Entry_t *VBR;
433
        VBR_Entry_t *VBR;
434
        MBR_Entry_t *MBR;
434
        MBR_Entry_t *MBR;
435
        File_t *file;
435
        File_t *file;
436
        uint8_t result = 0;
436
        uint8_t result = 0;
437
 
437
 
438
        printf("\r\n FAT16 init...");
438
        printf("\r\n FAT16 init...");
439
        Partition.IsValid = 0;
439
        Partition.IsValid = 0;
440
 
440
 
441
        // declare the filepointers as unused.
441
        // declare the filepointers as unused.
442
        for(cnt = 0; cnt < FILE_MAX_OPEN; cnt++)
442
        for(cnt = 0; cnt < FILE_MAX_OPEN; cnt++)
443
        {
443
        {
444
                FilePointer[cnt].State = FSTATE_UNUSED;
444
                FilePointer[cnt].State = FSTATE_UNUSED;
445
        }
445
        }
446
        // set current file pinter to first position in list
446
        // set current file pinter to first position in list
447
        file = &FilePointer[0];
447
        file = &FilePointer[0];
448
 
448
 
449
        // try to initialise the sd-card.
449
        // try to initialise the sd-card.
450
        if(SD_SUCCESS != SDC_Init())
450
        if(SD_SUCCESS != SDC_Init())
451
        {
451
        {
452
                printf("SD-Card could not be initialized.");
452
                printf("SD-Card could not be initialized.");
453
                result = 1;
453
                result = 1;
454
                goto end;
454
                goto end;
455
        }
455
        }
456
 
456
 
457
        // SD-Card is initialized successfully
457
        // SD-Card is initialized successfully
458
        if(SD_SUCCESS != SDC_GetSector((uint32_t)MBR_SECTOR,file->Cache))       // Read the MasterBootRecord
458
        if(SD_SUCCESS != SDC_GetSector((uint32_t)MBR_SECTOR,file->Cache))       // Read the MasterBootRecord
459
        {
459
        {
460
                printf("Error reading the MBR.");
460
                printf("Error reading the MBR.");
461
                result = 2;
461
                result = 2;
462
                goto end;
462
                goto end;
463
        }
463
        }
464
        MBR = (MBR_Entry_t *)file->Cache;                                               // Enter the MBR using the structure MBR_Entry_t.
464
        MBR = (MBR_Entry_t *)file->Cache;                                               // Enter the MBR using the structure MBR_Entry_t.
465
        if((MBR->PartitionEntry1.Type == PART_TYPE_FAT16_ST_32_MB) ||
465
        if((MBR->PartitionEntry1.Type == PART_TYPE_FAT16_ST_32_MB) ||
466
           (MBR->PartitionEntry1.Type == PART_TYPE_FAT16_LT_32_MB) ||
466
           (MBR->PartitionEntry1.Type == PART_TYPE_FAT16_LT_32_MB) ||
467
           (MBR->PartitionEntry1.Type == PART_TYPE_FAT16LBA))
467
           (MBR->PartitionEntry1.Type == PART_TYPE_FAT16LBA))
468
        {
468
        {
469
                // get sector offset 1st partition
469
                // get sector offset 1st partition
470
                partitionfirstsector = MBR->PartitionEntry1.NoSectorsBeforePartition;
470
                partitionfirstsector = MBR->PartitionEntry1.NoSectorsBeforePartition;
471
                // Start of Partition is the Volume Boot Sector
471
                // Start of Partition is the Volume Boot Sector
472
                if(SD_SUCCESS != SDC_GetSector(partitionfirstsector,file->Cache)) // Read the volume boot record
472
                if(SD_SUCCESS != SDC_GetSector(partitionfirstsector,file->Cache)) // Read the volume boot record
473
                {
473
                {
474
                        printf("Error reading the VBR.");
474
                        printf("Error reading the VBR.");
475
                        result = 3;
475
                        result = 3;
476
                        goto end;
476
                        goto end;
477
                }
477
                }
478
        }
478
        }
479
        else  // maybe the medium has no partition assuming sector 0 is the vbr
479
        else  // maybe the medium has no partition assuming sector 0 is the vbr
480
        {
480
        {
481
                partitionfirstsector = 0;
481
                partitionfirstsector = 0;
482
        }
482
        }
483
 
483
 
484
        VBR = (VBR_Entry_t *) file->Cache;                                              // Enter the VBR using the structure VBR_Entry_t.
484
        VBR = (VBR_Entry_t *) file->Cache;                                              // Enter the VBR using the structure VBR_Entry_t.
485
        if(VBR->BytesPerSector != BYTES_PER_SECTOR)
485
        if(VBR->BytesPerSector != BYTES_PER_SECTOR)
486
        {
486
        {
487
                printf("VBR: Sector size not supported.");
487
                printf("VBR: Sector size not supported.");
488
                result = 4;
488
                result = 4;
489
                goto end;
489
                goto end;
490
        }
490
        }
491
        Partition.SectorsPerCluster             = VBR->SectorsPerCluster;                       // Number of sectors per cluster. Depends on the memorysize of the sd-card.
491
        Partition.SectorsPerCluster             = VBR->SectorsPerCluster;                       // Number of sectors per cluster. Depends on the memorysize of the sd-card.
492
        Partition.FatCopies                     = VBR->NoFATCopies;                                     // Number of fatcopies.
492
        Partition.FatCopies                     = VBR->NoFATCopies;                                     // Number of fatcopies.
493
        Partition.MaxRootEntries                = VBR->MaxRootEntries;                          // How many Entries are possible in the rootdirectory (FAT16 allows max. 512 entries).
493
        Partition.MaxRootEntries                = VBR->MaxRootEntries;                          // How many Entries are possible in the rootdirectory (FAT16 allows max. 512 entries).
494
        Partition.SectorsPerFat                 = VBR->SectorsPerFAT;                           // The number of sectors per FAT.
494
        Partition.SectorsPerFat                 = VBR->SectorsPerFAT;                           // The number of sectors per FAT.
495
 
495
 
496
        /* Calculate the sectorpositon of the FAT, the Rootdirectory and the first Datacluster. */
496
        /* Calculate the sectorpositon of the FAT, the Rootdirectory and the first Datacluster. */
497
        // Calculate the position of the FileAllocationTable:
497
        // Calculate the position of the FileAllocationTable:
498
        // Start + # of Reserved Sectors
498
        // Start + # of Reserved Sectors
499
        Partition.FirstFatSector        =   (uint32_t)(partitionfirstsector + (uint32_t)(VBR->ReservedSectors));
499
        Partition.FirstFatSector        =   (uint32_t)(partitionfirstsector + (uint32_t)(VBR->ReservedSectors));
500
        // Calculate the position of the Rootdirectory:
500
        // Calculate the position of the Rootdirectory:
501
        // Start + # of Reserved Sectors + (# of Sectors Per FAT * # of FAT Copies)
501
        // Start + # of Reserved Sectors + (# of Sectors Per FAT * # of FAT Copies)
502
        Partition.FirstRootDirSector    =   Partition.FirstFatSector + (uint32_t)((uint32_t)Partition.SectorsPerFat*(uint32_t)Partition.FatCopies);
502
        Partition.FirstRootDirSector    =   Partition.FirstFatSector + (uint32_t)((uint32_t)Partition.SectorsPerFat*(uint32_t)Partition.FatCopies);
503
        // Calculate the position of the first datacluster:
503
        // Calculate the position of the first datacluster:
504
        // Start + # of Reserved + (# of Sectors Per FAT * # of FAT Copies) + ((Maximum Root Directory Entries * 32) / Bytes per Sector)
504
        // Start + # of Reserved + (# of Sectors Per FAT * # of FAT Copies) + ((Maximum Root Directory Entries * 32) / Bytes per Sector)
505
        Partition.FirstDataSector       =   Partition.FirstRootDirSector + (uint32_t)(Partition.MaxRootEntries>>4);  // assuming 512 Byte Per Sector
505
        Partition.FirstDataSector       =   Partition.FirstRootDirSector + (uint32_t)(Partition.MaxRootEntries>>4);  // assuming 512 Byte Per Sector
506
        // Calculate the last data sector
506
        // Calculate the last data sector
507
        if(VBR->NoSectors == 0)
507
        if(VBR->NoSectors == 0)
508
        {
508
        {
509
                printf("VBR: Bad number of sectors.");
509
                printf("VBR: Bad number of sectors.");
510
                result = 5;
510
                result = 5;
511
                goto end;
511
                goto end;
512
        }
512
        }
513
        Partition.LastDataSector = Partition.FirstDataSector + VBR->NoSectors - 1;
513
        Partition.LastDataSector = Partition.FirstDataSector + VBR->NoSectors - 1;
514
        // check for FAT16 in VBR of first partition
514
        // check for FAT16 in VBR of first partition
515
        if(!((VBR->FATName[0]=='F') && (VBR->FATName[1]=='A') && (VBR->FATName[2]=='T') && (VBR->FATName[3]=='1')&&(VBR->FATName[4]=='6')))
515
        if(!((VBR->FATName[0]=='F') && (VBR->FATName[1]=='A') && (VBR->FATName[2]=='T') && (VBR->FATName[3]=='1')&&(VBR->FATName[4]=='6')))
516
        {
516
        {
517
                printf("VBR: Partition ist not FAT16 type.");
517
                printf("VBR: Partition ist not FAT16 type.");
518
                result = 6;
518
                result = 6;
519
                goto end;
519
                goto end;
520
        }
520
        }
521
        Partition.IsValid = 1; // mark data in partition structure as valid
521
        Partition.IsValid = 1; // mark data in partition structure as valid
522
        result = 0;
522
        result = 0;
523
        end:
523
        end:
524
        if(result != 0) Fat16_Deinit();
524
        if(result != 0) Fat16_Deinit();
525
        else printf(" ...ok");
525
        else printf(" ...ok");
526
        return(result);
526
        return(result);
527
}
527
}
528
 
528
 
529
 
529
 
530
 
530
 
531
/****************************************************************************************************************************************/
531
/****************************************************************************************************************************************/
532
/* Function:    ClearCurrCluster(File_t*);                                                                                                                                                                                      */
532
/* Function:    ClearCurrCluster(File_t*);                                                                                                                                                                                      */
533
/*                                                                                                                                                                                                                                                                              */
533
/*                                                                                                                                                                                                                                                                              */
534
/* Description: This function fills the current cluster with 0.                                                                                                                                                 */
534
/* Description: This function fills the current cluster with 0.                                                                                                                                                 */
535
/*                                                                                                                                                                                                                                                                              */
535
/*                                                                                                                                                                                                                                                                              */
536
/* Returnvalue: The function returns 1 on success else 0.                                                                                                                                                               */
536
/* Returnvalue: The function returns 1 on success else 0.                                                                                                                                                               */
537
/****************************************************************************************************************************************/
537
/****************************************************************************************************************************************/
538
uint8_t ClearCurrCluster(File_t * file)
538
uint8_t ClearCurrCluster(File_t * file)
539
{
539
{
540
        uint8_t retvalue = 1;
540
        uint8_t retvalue = 1;
541
        uint32_t i;
541
        uint32_t i;
542
 
542
 
543
        if((!Partition.IsValid) || (file == NULL)) return(0);
543
        if((!Partition.IsValid) || (file == NULL)) return(0);
544
 
544
 
545
        for(i = 0; i < BYTES_PER_SECTOR; i++) file->Cache[i] = 0; // clear file cache
545
        for(i = 0; i < BYTES_PER_SECTOR; i++) file->Cache[i] = 0; // clear file cache
546
        for(i = 0; i < Partition.SectorsPerCluster; i++)
546
        for(i = 0; i < Partition.SectorsPerCluster; i++)
547
        {
547
        {
548
                file->SectorInCache = file->FirstSectorOfCurrCluster + i;
548
                file->SectorInCache = file->FirstSectorOfCurrCluster + i;
549
                if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))
549
                if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))
550
                {
550
                {
551
                        Fat16_Deinit();
551
                        Fat16_Deinit();
552
                        retvalue = 0;
552
                        retvalue = 0;
553
                }
553
                }
554
        }
554
        }
555
        return(retvalue);
555
        return(retvalue);
556
}
556
}
557
 
557
 
558
/*****************************************************************************************************************************************/
558
/*****************************************************************************************************************************************/
559
/* Function:    GetNextCluster(File_t* );                                                                                                                                                                                        */
559
/* Function:    GetNextCluster(File_t* );                                                                                                                                                                                        */
560
/*                                                                                                                                                                                                                                                                               */
560
/*                                                                                                                                                                                                                                                                               */
561
/* Description: This function finds the next datacluster of the file specified with File *File.                                                                                  */
561
/* Description: This function finds the next datacluster of the file specified with File *File.                                                                                  */
562
/*                                                                                                                                                                                                                                                                               */
562
/*                                                                                                                                                                                                                                                                               */
563
/* Returnvalue: The function returns the next cluster or 0 if the last cluster has already reached.                                                                                                      */
563
/* Returnvalue: The function returns the next cluster or 0 if the last cluster has already reached.                                                                                                      */
564
/*****************************************************************************************************************************************/
564
/*****************************************************************************************************************************************/
565
uint16_t GetNextCluster(File_t * file)
565
uint16_t GetNextCluster(File_t * file)
566
{
566
{
567
        uint16_t cluster = 0;
567
        uint16_t cluster = 0;
568
        uint32_t fat_byte_offset, sector, byte;
568
        uint32_t fat_byte_offset, sector, byte;
569
        Fat16Entry_t * fat;
569
        Fat16Entry_t * fat;
570
 
570
 
571
        if((!Partition.IsValid) || (file == NULL)) return(cluster);
571
        if((!Partition.IsValid) || (file == NULL)) return(cluster);
572
        // if sector is within the data area
572
        // if sector is within the data area
573
        if((Partition.FirstDataSector <= file->FirstSectorOfCurrCluster)&& (file->FirstSectorOfCurrCluster <= Partition.LastDataSector))
573
        if((Partition.FirstDataSector <= file->FirstSectorOfCurrCluster)&& (file->FirstSectorOfCurrCluster <= Partition.LastDataSector))
574
        {
574
        {
575
                // determine current file cluster
575
                // determine current file cluster
576
                cluster = SectorToFat16Cluster(file->FirstSectorOfCurrCluster);
576
                cluster = SectorToFat16Cluster(file->FirstSectorOfCurrCluster);
577
                // calculate byte offset in the fat for corresponding entry
577
                // calculate byte offset in the fat for corresponding entry
578
                fat_byte_offset = ((uint32_t)cluster)<<1; // two FAT bytes (16 bits) for every cluster
578
                fat_byte_offset = ((uint32_t)cluster)<<1; // two FAT bytes (16 bits) for every cluster
579
                // calculate the sector that contains the current cluster within the fat
579
                // calculate the sector that contains the current cluster within the fat
580
                sector = Partition.FirstFatSector + ( fat_byte_offset / BYTES_PER_SECTOR);
580
                sector = Partition.FirstFatSector + ( fat_byte_offset / BYTES_PER_SECTOR);
581
                // calculate byte offset of the current cluster within that fat sector
581
                // calculate byte offset of the current cluster within that fat sector
582
                byte = fat_byte_offset % BYTES_PER_SECTOR;
582
                byte = fat_byte_offset % BYTES_PER_SECTOR;
583
                // read this sector to the file cache
583
                // read this sector to the file cache
584
                if(file->SectorInCache != sector)
584
                if(file->SectorInCache != sector)
585
                {
585
                {
586
                        file->SectorInCache = sector;                                           // update sector stored in buffer
586
                        file->SectorInCache = sector;                                           // update sector stored in buffer
587
                        if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))       // read sector from sd-card
587
                        if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))       // read sector from sd-card
588
                        {
588
                        {
589
                                Fat16_Deinit();
589
                                Fat16_Deinit();
590
                                return (cluster);
590
                                return (cluster);
591
                        }
591
                        }
592
                }
592
                }
593
                // read the next cluster from cache
593
                // read the next cluster from cache
594
                fat = (Fat16Entry_t *)(&(file->Cache[byte]));
594
                fat = (Fat16Entry_t *)(&(file->Cache[byte]));
595
                cluster = fat->NextCluster;
595
                cluster = fat->NextCluster;
596
                // if last cluster fat entry
596
                // if last cluster fat entry
597
                if(FAT16_CLUSTER_LAST_MIN <= cluster)
597
                if(FAT16_CLUSTER_LAST_MIN <= cluster)
598
                {
598
                {
599
                         cluster = 0;
599
                         cluster = 0;
600
                }
600
                }
601
                else
601
                else
602
                {
602
                {
603
                        file->FirstSectorOfCurrCluster = Fat16ClusterToSector(cluster);
603
                        file->FirstSectorOfCurrCluster = Fat16ClusterToSector(cluster);
604
                        file->SectorOfCurrCluster = 0;
604
                        file->SectorOfCurrCluster = 0;
605
                        file->ByteOfCurrSector = 0;
605
                        file->ByteOfCurrSector = 0;
606
                }
606
                }
607
        }
607
        }
608
        return(cluster);
608
        return(cluster);
609
}
609
}
610
 
610
 
611
 
611
 
612
/****************************************************************************************************************************************/
612
/****************************************************************************************************************************************/
613
/* Function:    FindNextFreeCluster(File_t *);                                                                                                                                                                          */
613
/* Function:    FindNextFreeCluster(File_t *);                                                                                                                                                                          */
614
/*                                                                                                                                                                                                                                                                              */
614
/*                                                                                                                                                                                                                                                                              */
615
/* Description: This function looks in the fat to find the next free cluster                                                                                                                    */
615
/* Description: This function looks in the fat to find the next free cluster                                                                                                                    */
616
/*                                                                                                                                                                                                                                                                              */
616
/*                                                                                                                                                                                                                                                                              */
617
/* Returnvalue: The function returns the cluster number of the next free cluster found within the fat.                                                                  */
617
/* Returnvalue: The function returns the cluster number of the next free cluster found within the fat.                                                                  */
618
/****************************************************************************************************************************************/
618
/****************************************************************************************************************************************/
619
uint16_t FindNextFreeCluster(File_t *file)
619
uint16_t FindNextFreeCluster(File_t *file)
620
{
620
{
621
        uint32_t fat_sector;                            // current sector within the fat relative to the first sector of the fat.
621
        uint32_t fat_sector;                            // current sector within the fat relative to the first sector of the fat.
622
        uint32_t curr_sector;                           // current sector
622
        uint32_t curr_sector;                           // current sector
623
        uint16_t fat_entry;                                     // index to an fatentry within the actual sector (256 fatentries are possible within one sector).
623
        uint16_t fat_entry;                                     // index to an fatentry within the actual sector (256 fatentries are possible within one sector).
624
        uint16_t free_cluster = 0;                      // next free cluster number.
624
        uint16_t free_cluster = 0;                      // next free cluster number.
625
        Fat16Entry_t * fat;
625
        Fat16Entry_t * fat;
626
 
626
 
627
        if((!Partition.IsValid) || (file == NULL)) return(0);
627
        if((!Partition.IsValid) || (file == NULL)) return(0);
628
 
628
 
629
        // start searching for an empty cluster at the beginning of the fat.
629
        // start searching for an empty cluster at the beginning of the fat.
630
        fat_sector = 0;
630
        fat_sector = 0;
631
        do
631
        do
632
        {
632
        {
633
                curr_sector = Partition.FirstFatSector + fat_sector;    // calculate sector to read
633
                curr_sector = Partition.FirstFatSector + fat_sector;    // calculate sector to read
634
                file->SectorInCache = curr_sector;                                              // upate the sector number of file cache.
634
                file->SectorInCache = curr_sector;                                              // upate the sector number of file cache.
635
                if( SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))              // read sector of fat from sd-card.
635
                if( SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))              // read sector of fat from sd-card.
636
                {
636
                {
637
                        Fat16_Deinit();
637
                        Fat16_Deinit();
638
                        return(free_cluster);
638
                        return(free_cluster);
639
                }
639
                }
640
 
640
 
641
                fat = (Fat16Entry_t *)file->Cache;                                              // set fat pointer to file cache
641
                fat = (Fat16Entry_t *)file->Cache;                                              // set fat pointer to file cache
642
 
642
 
643
                for(fat_entry = 0; fat_entry < FAT16_ENTRIES_PER_SECTOR; fat_entry++)                                           // look for an free cluster at all entries in this sector of the fat.
643
                for(fat_entry = 0; fat_entry < FAT16_ENTRIES_PER_SECTOR; fat_entry++)                                           // look for an free cluster at all entries in this sector of the fat.
644
                {
644
                {
645
                        if(fat[fat_entry].NextCluster == FAT16_CLUSTER_FREE)            // empty cluster found!!
645
                        if(fat[fat_entry].NextCluster == FAT16_CLUSTER_FREE)            // empty cluster found!!
646
                        {
646
                        {
647
                                fat[fat_entry].NextCluster = FAT16_CLUSTER_LAST_MAX;    // mark this fat-entry as used
647
                                fat[fat_entry].NextCluster = FAT16_CLUSTER_LAST_MAX;    // mark this fat-entry as used
648
                                if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))               // and save the sector at the sd-card.
648
                                if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))               // and save the sector at the sd-card.
649
                                {
649
                                {
650
                                        Fat16_Deinit();
650
                                        Fat16_Deinit();
651
                                        return(free_cluster);
651
                                        return(free_cluster);
652
                                }
652
                                }
653
                                free_cluster = (uint16_t)(fat_sector * FAT16_ENTRIES_PER_SECTOR + (uint32_t)fat_entry);
653
                                free_cluster = (uint16_t)(fat_sector * FAT16_ENTRIES_PER_SECTOR + (uint32_t)fat_entry);
654
                                fat_entry = FAT16_ENTRIES_PER_SECTOR;                                   // terminate the search for a free cluster in this sector.
654
                                fat_entry = FAT16_ENTRIES_PER_SECTOR;                                   // terminate the search for a free cluster in this sector.
655
                        }
655
                        }
656
                }
656
                }
657
                fat_sector++;                                                                                                   // continue the search in next fat sector
657
                fat_sector++;                                                                                                   // continue the search in next fat sector
658
        // repeat until the end of the fat is  reached and no free cluster has been found so far
658
        // repeat until the end of the fat is  reached and no free cluster has been found so far
659
        }while((fat_sector < Partition.SectorsPerFat) && (!free_cluster));
659
        }while((fat_sector < Partition.SectorsPerFat) && (!free_cluster));
660
        return(free_cluster);
660
        return(free_cluster);
661
}
661
}
662
 
662
 
663
 
663
 
664
/****************************************************************************************************************************************************/
664
/****************************************************************************************************************************************************/
665
/* Function:    int16_t fseek_(File_t *, int32_t *, uint8_t)                                                                                                                                                                                                            */
665
/* Function:    int16_t fseek_(File_t *, int32_t *, uint8_t)                                                                                                                                                                                                            */
666
/*                                                                                                                                                                                                                                                                                                      */
666
/*                                                                                                                                                                                                                                                                                                      */
667
/* Description: This function sets the pointer of the stream relative to the position                                                                                                                           */
667
/* Description: This function sets the pointer of the stream relative to the position                                                                                                                           */
668
/*                              specified by origin (SEEK_SET, SEEK_CUR, SEEK_END)                                                                                                                                                                      */
668
/*                              specified by origin (SEEK_SET, SEEK_CUR, SEEK_END)                                                                                                                                                                      */
669
/* Returnvalue: Is 1 if seek was successful                                                                                                                                                                                                                                                                     */
669
/* Returnvalue: Is 1 if seek was successful                                                                                                                                                                                                                                                                     */
670
/****************************************************************************************************************************************************/
670
/****************************************************************************************************************************************************/
671
int16_t fseek_(File_t * const file, int32_t offset, int16_t origin)
671
int16_t fseek_(File_t * const file, int32_t offset, int16_t origin)
672
{
672
{
673
        int32_t         fposition       = 0;
673
        int32_t         fposition       = 0;
674
        int16_t         retvalue        = 1;
674
        int16_t         retvalue        = 1;
675
 
675
 
676
        if((!Partition.IsValid) || (file == NULL)) return(0);
676
        if((!Partition.IsValid) || (file == NULL)) return(0);
677
        switch(origin)
677
        switch(origin)
678
        {
678
        {
679
                case SEEK_SET:                          // Fileposition relative to the beginning of the file.
679
                case SEEK_SET:                          // Fileposition relative to the beginning of the file.
680
                        fposition = 0;
680
                        fposition = 0;
681
                        break;
681
                        break;
682
                case SEEK_END:                          // Fileposition relative to the end of the file.
682
                case SEEK_END:                          // Fileposition relative to the end of the file.
683
                        fposition = (int32_t)file->Size;
683
                        fposition = (int32_t)file->Size;
684
                        break;
684
                        break;
685
                case SEEK_CUR:                          // Fileposition relative to the current position of the file.
685
                case SEEK_CUR:                          // Fileposition relative to the current position of the file.
686
                default:
686
                default:
687
                        fposition = file->Position;
687
                        fposition = file->Position;
688
                        break;
688
                        break;
689
        }
689
        }
690
 
690
 
691
        fposition += offset;
691
        fposition += offset;
692
 
692
 
693
        if((fposition >= 0) && (fposition <= (int32_t)file->Size))              // is the pointer still within the file?
693
        if((fposition >= 0) && (fposition <= (int32_t)file->Size))              // is the pointer still within the file?
694
        {
694
        {
695
                // reset file position to start of the file
695
                // reset file position to start of the file
696
                file->FirstSectorOfCurrCluster = file->FirstSectorOfFirstCluster;
696
                file->FirstSectorOfCurrCluster = file->FirstSectorOfFirstCluster;
697
                file->SectorOfCurrCluster       = 0;
697
                file->SectorOfCurrCluster       = 0;
698
                file->ByteOfCurrSector          = 0;
698
                file->ByteOfCurrSector          = 0;
699
                file->Position                          = 0;
699
                file->Position                          = 0;
700
 
700
 
701
                while(file->Position < fposition)       // repeat until the current position is less than target
701
                while(file->Position < fposition)       // repeat until the current position is less than target
702
                {
702
                {
703
                        file->Position++;                               // increment file position
703
                        file->Position++;                               // increment file position
704
                        file->ByteOfCurrSector++;               // next byte in current sector
704
                        file->ByteOfCurrSector++;               // next byte in current sector
705
                        if(file->ByteOfCurrSector >= BYTES_PER_SECTOR)
705
                        if(file->ByteOfCurrSector >= BYTES_PER_SECTOR)
706
                        {
706
                        {
707
                                file->ByteOfCurrSector = 0;                                                                             // reading at the beginning of new sector.
707
                                file->ByteOfCurrSector = 0;                                                                             // reading at the beginning of new sector.
708
                                file->SectorOfCurrCluster++;                                                                    // continue reading in next sector
708
                                file->SectorOfCurrCluster++;                                                                    // continue reading in next sector
709
                                if(file->SectorOfCurrCluster >= Partition.SectorsPerCluster)    // if end of cluster is reached, the next datacluster has to be searched in the FAT.
709
                                if(file->SectorOfCurrCluster >= Partition.SectorsPerCluster)    // if end of cluster is reached, the next datacluster has to be searched in the FAT.
710
                                {
710
                                {
711
                                        if(GetNextCluster(file))                                                                        // Sets the clusterpointer of the file to the next datacluster.
711
                                        if(GetNextCluster(file))                                                                        // Sets the clusterpointer of the file to the next datacluster.
712
                                        {
712
                                        {
713
                                                file->SectorOfCurrCluster = 0;
713
                                                file->SectorOfCurrCluster = 0;
714
                                        }
714
                                        }
715
                                        else // the last cluster was allready reached
715
                                        else // the last cluster was allready reached
716
                                        {
716
                                        {
717
                                                file->SectorOfCurrCluster--;                                                    // jump back to the ast sector in the last cluster
717
                                                file->SectorOfCurrCluster--;                                                    // jump back to the ast sector in the last cluster
718
                                                file->ByteOfCurrSector = BYTES_PER_SECTOR;                              // set ByteOfCurrSector one byte over sector end
718
                                                file->ByteOfCurrSector = BYTES_PER_SECTOR;                              // set ByteOfCurrSector one byte over sector end
719
                                        }
719
                                        }
720
                                }
720
                                }
721
                        }
721
                        }
722
                }
722
                }
723
        }
723
        }
724
        if(file->Position == fposition) retvalue = 0;
724
        if(file->Position == fposition) retvalue = 0;
725
        return(retvalue);
725
        return(retvalue);
726
}
726
}
727
 
727
 
728
 
728
 
729
/****************************************************************************************************************************************/
729
/****************************************************************************************************************************************/
730
/* Function:    uint16_t DeleteClusterChain(File *file);                                                                                                                                                                                */
730
/* Function:    uint16_t DeleteClusterChain(File *file);                                                                                                                                                                                */
731
/*                                                                                                                                                                                                                                                                              */
731
/*                                                                                                                                                                                                                                                                              */
732
/* Description: This function trances along a cluster chain in the fat and frees all clusters visited.                                                                  */
732
/* Description: This function trances along a cluster chain in the fat and frees all clusters visited.                                                                  */
733
/*                                                                                                                                                                                                                                                                              */
733
/*                                                                                                                                                                                                                                                                              */
734
/****************************************************************************************************************************************/
734
/****************************************************************************************************************************************/
735
uint8_t DeleteClusterChain(uint16_t StartCluster)
735
uint8_t DeleteClusterChain(uint16_t StartCluster)
736
{
736
{
737
        uint16_t cluster;
737
        uint16_t cluster;
738
        uint32_t fat_byte_offset, sector, byte;
738
        uint32_t fat_byte_offset, sector, byte;
739
        Fat16Entry_t * fat;
739
        Fat16Entry_t * fat;
740
        uint8_t buffer[BYTES_PER_SECTOR];
740
        uint8_t buffer[BYTES_PER_SECTOR];
741
        uint32_t sector_in_buffer = 0;
741
        uint32_t sector_in_buffer = 0;
742
        uint8_t repeat = 0;
742
        uint8_t repeat = 0;
743
 
743
 
744
        if(!Partition.IsValid) return 0;
744
        if(!Partition.IsValid) return 0;
745
 
745
 
746
        cluster = StartCluster; // init chain trace
746
        cluster = StartCluster; // init chain trace
747
        // calculate byte offset in the fat for corresponding entry
747
        // calculate byte offset in the fat for corresponding entry
748
        fat_byte_offset = ((uint32_t)cluster)<<1; // two FAT bytes (16 bits) for every cluster
748
        fat_byte_offset = ((uint32_t)cluster)<<1; // two FAT bytes (16 bits) for every cluster
749
        // calculate the sector that contains the current cluster within the fat
749
        // calculate the sector that contains the current cluster within the fat
750
        sector = Partition.FirstFatSector + ( fat_byte_offset / BYTES_PER_SECTOR);
750
        sector = Partition.FirstFatSector + ( fat_byte_offset / BYTES_PER_SECTOR);
751
        // calculate byte offset of the current cluster within that fat sector
751
        // calculate byte offset of the current cluster within that fat sector
752
        byte = fat_byte_offset % BYTES_PER_SECTOR;
752
        byte = fat_byte_offset % BYTES_PER_SECTOR;
753
        do
753
        do
754
        {
754
        {
755
                if(sector != sector_in_buffer)
755
                if(sector != sector_in_buffer)
756
                {
756
                {
757
                        // read this sector to buffer
757
                        // read this sector to buffer
758
                        sector_in_buffer = sector;
758
                        sector_in_buffer = sector;
759
                        if(SD_SUCCESS != SDC_GetSector(sector_in_buffer, buffer)) return 0;     // read sector from sd-card
759
                        if(SD_SUCCESS != SDC_GetSector(sector_in_buffer, buffer)) return 0;     // read sector from sd-card
760
                }
760
                }
761
                // read the next cluster from cache
761
                // read the next cluster from cache
762
                fat = (Fat16Entry_t *)(&(buffer[byte]));
762
                fat = (Fat16Entry_t *)(&(buffer[byte]));
763
                cluster = fat->NextCluster;
763
                cluster = fat->NextCluster;
764
                if((FAT16_CLUSTER_USED_MIN <= cluster) && (cluster <= FAT16_CLUSTER_USED_MAX) ) repeat = 1;
764
                if((FAT16_CLUSTER_USED_MIN <= cluster) && (cluster <= FAT16_CLUSTER_USED_MAX) ) repeat = 1;
765
                else repeat = 0;
765
                else repeat = 0;
766
 
766
 
767
                fat->NextCluster =      FAT16_CLUSTER_FREE; // mark current cluster as free
767
                fat->NextCluster =      FAT16_CLUSTER_FREE; // mark current cluster as free
768
                // calculate byte offset in the fat for corresponding entry
768
                // calculate byte offset in the fat for corresponding entry
769
                fat_byte_offset = ((uint32_t)cluster)<<1; // two FAT bytes (16 bits) for every cluster
769
                fat_byte_offset = ((uint32_t)cluster)<<1; // two FAT bytes (16 bits) for every cluster
770
                // calculate the sector that contains the current cluster within the fat
770
                // calculate the sector that contains the current cluster within the fat
771
                sector = Partition.FirstFatSector + ( fat_byte_offset / BYTES_PER_SECTOR);
771
                sector = Partition.FirstFatSector + ( fat_byte_offset / BYTES_PER_SECTOR);
772
                // calculate byte offset of the current cluster within that fat sector
772
                // calculate byte offset of the current cluster within that fat sector
773
                byte = fat_byte_offset % BYTES_PER_SECTOR;
773
                byte = fat_byte_offset % BYTES_PER_SECTOR;
774
                // if new sector is not the sector in buffer or the last cluster in the chain was traced
774
                // if new sector is not the sector in buffer or the last cluster in the chain was traced
775
                if((sector != sector_in_buffer) || !repeat)
775
                if((sector != sector_in_buffer) || !repeat)
776
                {       // write sector in buffer
776
                {       // write sector in buffer
777
                        if(SD_SUCCESS != SDC_PutSector(sector_in_buffer,buffer)) return 0;
777
                        if(SD_SUCCESS != SDC_PutSector(sector_in_buffer,buffer)) return 0;
778
                }
778
                }
779
        }
779
        }
780
        while(repeat);
780
        while(repeat);
781
 
781
 
782
        return 1;
782
        return 1;
783
}
783
}
784
 
784
 
785
 
785
 
786
/****************************************************************************************************************************************/
786
/****************************************************************************************************************************************/
787
/* Function:    uint16_t AppendCluster(File *file);                                                                                                                                                                                     */
787
/* Function:    uint16_t AppendCluster(File *file);                                                                                                                                                                                     */
788
/*                                                                                                                                                                                                                                                                              */
788
/*                                                                                                                                                                                                                                                                              */
789
/* Description: This function looks in the fat to find the next free cluster and appends it to the file.                                                                */
789
/* Description: This function looks in the fat to find the next free cluster and appends it to the file.                                                                */
790
/*                                                                                                                                                                                                                                                                              */
790
/*                                                                                                                                                                                                                                                                              */
791
/* Returnvalue: The function returns the appened cluster number or 0 of no cluster was appended.                                                                                                                                                */
791
/* Returnvalue: The function returns the appened cluster number or 0 of no cluster was appended.                                                                                                                                                */
792
/****************************************************************************************************************************************/
792
/****************************************************************************************************************************************/
793
uint16_t AppendCluster(File_t *file)
793
uint16_t AppendCluster(File_t *file)
794
{
794
{
795
        uint16_t last_cluster, new_cluster = 0;
795
        uint16_t last_cluster, new_cluster = 0;
796
        uint32_t fat_byte_offset, sector, byte;
796
        uint32_t fat_byte_offset, sector, byte;
797
        Fat16Entry_t * fat;
797
        Fat16Entry_t * fat;
798
 
798
 
799
        if((!Partition.IsValid) || (file == NULL)) return(new_cluster);
799
        if((!Partition.IsValid) || (file == NULL)) return(new_cluster);
800
 
800
 
801
        new_cluster = FindNextFreeCluster(file);        // the next free cluster found on the disk.
801
        new_cluster = FindNextFreeCluster(file);        // the next free cluster found on the disk.
802
        if(new_cluster)
802
        if(new_cluster)
803
        {       // A free cluster was found and can be added to the end of the file.
803
        {       // A free cluster was found and can be added to the end of the file.
804
                fseek_(file, 0, SEEK_END);                                                                                                      // jump to the end of the file
804
                fseek_(file, 0, SEEK_END);                                                                                                      // jump to the end of the file
805
                last_cluster = SectorToFat16Cluster(file->FirstSectorOfCurrCluster);            // determine current file cluster
805
                last_cluster = SectorToFat16Cluster(file->FirstSectorOfCurrCluster);            // determine current file cluster
806
                fat_byte_offset = ((uint32_t)last_cluster)<<1;
806
                fat_byte_offset = ((uint32_t)last_cluster)<<1;
807
                sector = Partition.FirstFatSector + ( fat_byte_offset / BYTES_PER_SECTOR);
807
                sector = Partition.FirstFatSector + ( fat_byte_offset / BYTES_PER_SECTOR);
808
                byte = fat_byte_offset % BYTES_PER_SECTOR;
808
                byte = fat_byte_offset % BYTES_PER_SECTOR;
809
 
809
 
810
                if(file->SectorInCache != sector)
810
                if(file->SectorInCache != sector)
811
                {
811
                {
812
                        file->SectorInCache = sector;                                           // update sector stored in buffer
812
                        file->SectorInCache = sector;                                           // update sector stored in buffer
813
                        if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))       // read sector from sd-card
813
                        if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))       // read sector from sd-card
814
                        {
814
                        {
815
                                Fat16_Deinit();
815
                                Fat16_Deinit();
816
                                return(0);
816
                                return(0);
817
                        }
817
                        }
818
                }
818
                }
819
                fat = (Fat16Entry_t *)(&(file->Cache[byte]));
819
                fat = (Fat16Entry_t *)(&(file->Cache[byte]));
820
                fat->NextCluster = new_cluster;                                                 // append the free cluster to the end of the file in the FAT.
820
                fat->NextCluster = new_cluster;                                                 // append the free cluster to the end of the file in the FAT.
821
                if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))               // save the modified sector to the FAT.
821
                if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))               // save the modified sector to the FAT.
822
                {
822
                {
823
                        Fat16_Deinit();
823
                        Fat16_Deinit();
824
                        return(0);
824
                        return(0);
825
                }
825
                }
826
                file->FirstSectorOfCurrCluster = Fat16ClusterToSector(new_cluster);
826
                file->FirstSectorOfCurrCluster = Fat16ClusterToSector(new_cluster);
827
                file->SectorOfCurrCluster = 0;
827
                file->SectorOfCurrCluster = 0;
828
                file->ByteOfCurrSector = 0;
828
                file->ByteOfCurrSector = 0;
829
        }
829
        }
830
        return(new_cluster);
830
        return(new_cluster);
831
}
831
}
832
 
832
 
833
/****************************************************************************************************************************************************/
833
/****************************************************************************************************************************************************/
834
/* Function:    DirectoryEntryExist(int8_t *, uint8_t, uint8_t, File_t *)                                                                                                                                                                                       */
834
/* Function:    DirectoryEntryExist(int8_t *, uint8_t, uint8_t, File_t *)                                                                                                                                                                                       */
835
/*                                                                                                                                                                                                                                                                                                      */
835
/*                                                                                                                                                                                                                                                                                                      */
836
/* Description: This function searches all possible dir entries until the file or directory is found or the end of the directory is reached                     */
836
/* Description: This function searches all possible dir entries until the file or directory is found or the end of the directory is reached                     */
837
/*                                                                                                                                                                                                                                                                                                      */
837
/*                                                                                                                                                                                                                                                                                                      */
838
/* Returnvalue: This function returns 1 if the directory entry specified was found.                                                                                                                                     */
838
/* Returnvalue: This function returns 1 if the directory entry specified was found.                                                                                                                                     */
839
/****************************************************************************************************************************************************/
839
/****************************************************************************************************************************************************/
840
uint8_t DirectoryEntryExist(int8_t *dirname, uint8_t attribfilter, uint8_t attribmask, File_t *file)
840
uint8_t DirectoryEntryExist(int8_t *dirname, uint8_t attribfilter, uint8_t attribmask, File_t *file)
841
{
841
{
842
        uint32_t        dir_sector, max_dir_sector, curr_sector;
842
        uint32_t        dir_sector, max_dir_sector, curr_sector;
843
        uint16_t        dir_entry = 0;
843
        uint16_t        dir_entry = 0;
844
 
844
 
845
        uint16_t        end_of_directory_not_reached = 0;
845
        uint16_t        end_of_directory_not_reached = 0;
846
        uint8_t         i = 0;
846
        uint8_t         i = 0;
847
        uint8_t         direntry_exist = 0;
847
        uint8_t         direntry_exist = 0;
848
        DirEntry_t * dir;
848
        DirEntry_t * dir;
849
 
849
 
850
        // if incomming pointers are useless return immediatly
850
        // if incomming pointers are useless return immediatly
851
        if((!Partition.IsValid) || (file == NULL) || (dirname == NULL)) return(direntry_exist);
851
        if((!Partition.IsValid) || (file == NULL) || (dirname == NULL)) return(direntry_exist);
852
 
852
 
853
        // dir entries can be searched only in filesclusters that have
853
        // dir entries can be searched only in filesclusters that have
854
        // a corresponding dir entry with adir-flag set in its attribute
854
        // a corresponding dir entry with adir-flag set in its attribute
855
        // or direct within the root directory area
855
        // or direct within the root directory area
856
 
856
 
857
        file->FirstSectorOfFirstCluster = 0;
857
        file->FirstSectorOfFirstCluster = 0;
858
        // no current directory exist therefore assume searching in the root
858
        // no current directory exist therefore assume searching in the root
859
        if(file->DirectorySector == 0)
859
        if(file->DirectorySector == 0)
860
        {
860
        {
861
                max_dir_sector = (Partition.MaxRootEntries * DIRENTRY_SIZE)/BYTES_PER_SECTOR;
861
                max_dir_sector = (Partition.MaxRootEntries * DIRENTRY_SIZE)/BYTES_PER_SECTOR;
862
                file->FirstSectorOfFirstCluster = Partition.FirstRootDirSector;
862
                file->FirstSectorOfFirstCluster = Partition.FirstRootDirSector;
863
        }
863
        }
864
        // within the root directory area we can read sectors sequentially until the end of this area
864
        // within the root directory area we can read sectors sequentially until the end of this area
865
        else if((Partition.FirstRootDirSector <= file->DirectorySector) && (file->DirectorySector < Partition.FirstDataSector))
865
        else if((Partition.FirstRootDirSector <= file->DirectorySector) && (file->DirectorySector < Partition.FirstDataSector))
866
        {
866
        {
867
                max_dir_sector = (Partition.MaxRootEntries * DIRENTRY_SIZE)/BYTES_PER_SECTOR;
867
                max_dir_sector = (Partition.MaxRootEntries * DIRENTRY_SIZE)/BYTES_PER_SECTOR;
868
        }
868
        }
869
        // within the data clusters we can read sectors sequentially only within the cluster
869
        // within the data clusters we can read sectors sequentially only within the cluster
870
        else if((Partition.FirstDataSector <= file->DirectorySector) && (file->DirectorySector <= Partition.LastDataSector))
870
        else if((Partition.FirstDataSector <= file->DirectorySector) && (file->DirectorySector <= Partition.LastDataSector))
871
        {
871
        {
872
                max_dir_sector = Partition.SectorsPerCluster;                           // limit max secters before next cluster
872
                max_dir_sector = Partition.SectorsPerCluster;                           // limit max secters before next cluster
873
        }
873
        }
874
        else return (direntry_exist); // bad sector range for directory sector of the file
874
        else return (direntry_exist); // bad sector range for directory sector of the file
875
        // if search area is not defined yet
875
        // if search area is not defined yet
876
        if(file->FirstSectorOfFirstCluster == 0)
876
        if(file->FirstSectorOfFirstCluster == 0)
877
        {
877
        {
878
                // check if the directory entry of current file is existent and has the dir-flag set
878
                // check if the directory entry of current file is existent and has the dir-flag set
879
                file->SectorInCache = file->DirectorySector;                            // update the sector number of file cache.
879
                file->SectorInCache = file->DirectorySector;                            // update the sector number of file cache.
880
                if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector.
880
                if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector.
881
                {
881
                {
882
                        Fat16_Deinit();
882
                        Fat16_Deinit();
883
                        return(direntry_exist);
883
                        return(direntry_exist);
884
                }
884
                }
885
                dir = (DirEntry_t *)file->Cache;                                                        // set pointer to directory
885
                dir = (DirEntry_t *)file->Cache;                                                        // set pointer to directory
886
                switch((uint8_t)dir[file->DirectoryIndex].Name[0])                                      // check if current directory exist
886
                switch((uint8_t)dir[file->DirectoryIndex].Name[0])                                      // check if current directory exist
887
                {
887
                {
888
                        case SLOT_EMPTY:
888
                        case SLOT_EMPTY:
889
                        case SLOT_DELETED:
889
                        case SLOT_DELETED:
890
                                // the directrory pointer of this file points to a deleted or not existen directory
890
                                // the directrory pointer of this file points to a deleted or not existen directory
891
                                // therefore no file or subdirectory can be created
891
                                // therefore no file or subdirectory can be created
892
                                return (direntry_exist);
892
                                return (direntry_exist);
893
                                break;
893
                                break;
894
                        default:        // and is a real directory
894
                        default:        // and is a real directory
895
                                if((dir[file->DirectoryIndex].Attribute & ATTR_SUBDIRECTORY) != ATTR_SUBDIRECTORY)
895
                                if((dir[file->DirectoryIndex].Attribute & ATTR_SUBDIRECTORY) != ATTR_SUBDIRECTORY)
896
                                {       // current file is not a directory therefore no file or subdirectory can be created here
896
                                {       // current file is not a directory therefore no file or subdirectory can be created here
897
                                        return (direntry_exist);
897
                                        return (direntry_exist);
898
                                }
898
                                }
899
                                break;
899
                                break;
900
                }
900
                }
901
                file->FirstSectorOfFirstCluster = Fat16ClusterToSector(dir[file->DirectoryIndex].StartCluster);
901
                file->FirstSectorOfFirstCluster = Fat16ClusterToSector(dir[file->DirectoryIndex].StartCluster);
902
        }
902
        }
903
 
903
 
904
        // update current file data area position to start of first cluster
904
        // update current file data area position to start of first cluster
905
        file->FirstSectorOfCurrCluster  = file->FirstSectorOfFirstCluster;
905
        file->FirstSectorOfCurrCluster  = file->FirstSectorOfFirstCluster;
906
        file->SectorOfCurrCluster               = 0;
906
        file->SectorOfCurrCluster               = 0;
907
        file->ByteOfCurrSector                  = 0;
907
        file->ByteOfCurrSector                  = 0;
908
 
908
 
909
        do // loop over all data clusters of the current directory entry
909
        do // loop over all data clusters of the current directory entry
910
        {
910
        {
911
                dir_sector = 0; // reset sector counter within a new cluster
911
                dir_sector = 0; // reset sector counter within a new cluster
912
                do // loop over all sectors of a cluster or all sectors of the root directory
912
                do // loop over all sectors of a cluster or all sectors of the root directory
913
                {
913
                {
914
                        curr_sector = file->FirstSectorOfCurrCluster + dir_sector;      // calculate sector number
914
                        curr_sector = file->FirstSectorOfCurrCluster + dir_sector;      // calculate sector number
915
                        file->SectorInCache = curr_sector;                                                      // upate the sector number of file cache.
915
                        file->SectorInCache = curr_sector;                                                      // upate the sector number of file cache.
916
                        if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read the sector
916
                        if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read the sector
917
                        {
917
                        {
918
                                Fat16_Deinit();
918
                                Fat16_Deinit();
919
                                return(direntry_exist);
919
                                return(direntry_exist);
920
                        }
920
                        }
921
                        dir = (DirEntry_t *)file->Cache;                                                        // set pointer to directory
921
                        dir = (DirEntry_t *)file->Cache;                                                        // set pointer to directory
922
                        // search all directory entries within that sector
922
                        // search all directory entries within that sector
923
                        for(dir_entry = 0; dir_entry < DIRENTRIES_PER_SECTOR; dir_entry++)
923
                        for(dir_entry = 0; dir_entry < DIRENTRIES_PER_SECTOR; dir_entry++)
924
                        {   // check for existing dir entry
924
                        {   // check for existing dir entry
925
                                switch((uint8_t)dir[dir_entry].Name[0])
925
                                switch((uint8_t)dir[dir_entry].Name[0])
926
                                {
926
                                {
927
                                        case SLOT_EMPTY:
927
                                        case SLOT_EMPTY:
928
                                        case SLOT_DELETED:
928
                                        case SLOT_DELETED:
929
                                                // ignore empty or deleted dir entries
929
                                                // ignore empty or deleted dir entries
930
                                                break;
930
                                                break;
931
                                        default:
931
                                        default:
932
                                                // if existing check attributes before names are compared will safe performance
932
                                                // if existing check attributes before names are compared will safe performance
933
                                                if ((dir[dir_entry].Attribute & attribmask) != attribfilter) break; // attribute must match
933
                                                if ((dir[dir_entry].Attribute & attribmask) != attribfilter) break; // attribute must match
934
                                                // then compare the name to the giveb dirname (first 11 characters include 8 chars of basename and 3 chars extension.)
934
                                                // then compare the name to the giveb dirname (first 11 characters include 8 chars of basename and 3 chars extension.)
935
                                                i = 0;
935
                                                i = 0;
936
                                                while((i < 11) && (dir[dir_entry].Name[i] == dirname[i])) i++;
936
                                                while((i < 11) && (dir[dir_entry].Name[i] == dirname[i])) i++;
937
                                                if (i < 10) break; // names does not match
937
                                                if (i < 10) break; // names does not match
938
                                                // if dirname and attribute have matched
938
                                                // if dirname and attribute have matched
939
                                                file->Attribute = dir[dir_entry].Attribute; // store attribute of found dir entry
939
                                                file->Attribute = dir[dir_entry].Attribute; // store attribute of found dir entry
940
                                                file->FirstSectorOfFirstCluster = Fat16ClusterToSector(dir[dir_entry].StartCluster); // set sector of first data cluster
940
                                                file->FirstSectorOfFirstCluster = Fat16ClusterToSector(dir[dir_entry].StartCluster); // set sector of first data cluster
941
                                                file->FirstSectorOfCurrCluster = file->FirstSectorOfFirstCluster;
941
                                                file->FirstSectorOfCurrCluster = file->FirstSectorOfFirstCluster;
942
                                                file->SectorOfCurrCluster = 0;
942
                                                file->SectorOfCurrCluster = 0;
943
                                                file->ByteOfCurrSector = 0;
943
                                                file->ByteOfCurrSector = 0;
944
                                                file->DirectorySector = curr_sector; // current sector
944
                                                file->DirectorySector = curr_sector; // current sector
945
                                                file->DirectoryIndex  = dir_entry; // current direntry in current sector
945
                                                file->DirectoryIndex  = dir_entry; // current direntry in current sector
946
                                                file->Size = dir[dir_entry].Size;
946
                                                file->Size = dir[dir_entry].Size;
947
                                                direntry_exist = 1; // mark as found
947
                                                direntry_exist = 1; // mark as found
948
                                                dir_entry = DIRENTRIES_PER_SECTOR;      // stop for-loop
948
                                                dir_entry = DIRENTRIES_PER_SECTOR;      // stop for-loop
949
                                } // end of first byte of name check
949
                                } // end of first byte of name check
950
                        }
950
                        }
951
                        dir_sector++; // search next sector
951
                        dir_sector++; // search next sector
952
                // stop if we reached the end of the cluster or the end of the root dir
952
                // stop if we reached the end of the cluster or the end of the root dir
953
                }while((dir_sector < max_dir_sector) && (!direntry_exist));
953
                }while((dir_sector < max_dir_sector) && (!direntry_exist));
954
 
954
 
955
                // if we are seaching in the data area and the file not found in this cluster so take next cluster.
955
                // if we are seaching in the data area and the file not found in this cluster so take next cluster.
956
                if(!direntry_exist && ( Partition.FirstDataSector <= file->FirstSectorOfCurrCluster))
956
                if(!direntry_exist && ( Partition.FirstDataSector <= file->FirstSectorOfCurrCluster))
957
                {
957
                {
958
                        end_of_directory_not_reached = GetNextCluster(file);  // updates File->FirstSectorOfCurrCluster
958
                        end_of_directory_not_reached = GetNextCluster(file);  // updates File->FirstSectorOfCurrCluster
959
                }
959
                }
960
        }while((end_of_directory_not_reached) && (!direntry_exist)); // repeat until a next cluster exist an no
960
        }while((end_of_directory_not_reached) && (!direntry_exist)); // repeat until a next cluster exist an no
961
        return(direntry_exist);
961
        return(direntry_exist);
962
}
962
}
963
 
963
 
964
 
964
 
965
/****************************************************************************************************************************************/
965
/****************************************************************************************************************************************/
966
/*      Function:               CreateDirectoryEntry(int8_t *, uint16_t, File_t *)                                                                                                                                                      */
966
/*      Function:               CreateDirectoryEntry(int8_t *, uint16_t, File_t *)                                                                                                                                                      */
967
/*                                                                                                                                                                                                                                                                              */
967
/*                                                                                                                                                                                                                                                                              */
968
/*      Description:    This function looks for the next free position in the directory and creates an entry.                                                           */
968
/*      Description:    This function looks for the next free position in the directory and creates an entry.                                                           */
969
/*                                      The type of an directory entry is specified by the file attribute.                                                                                                      */
969
/*                                      The type of an directory entry is specified by the file attribute.                                                                                                      */
970
/*                                                                                                                                                                                                                                                                              */
970
/*                                                                                                                                                                                                                                                                              */
971
/*      Returnvalue:    Return 0 on error                                                                                                                                                                                                       */
971
/*      Returnvalue:    Return 0 on error                                                                                                                                                                                                       */
972
/****************************************************************************************************************************************/
972
/****************************************************************************************************************************************/
973
uint8_t CreateDirectoryEntry(int8_t *dirname, uint8_t attrib, File_t *file)
973
uint8_t CreateDirectoryEntry(int8_t *dirname, uint8_t attrib, File_t *file)
974
{
974
{
975
        uint32_t        dir_sector, max_dir_sector, curr_sector;
975
        uint32_t        dir_sector, max_dir_sector, curr_sector;
976
        uint16_t        dir_entry       = 0;
976
        uint16_t        dir_entry       = 0;
977
        uint16_t        subdircluster, dircluster = 0;
977
        uint16_t        subdircluster, dircluster = 0;
978
        uint16_t        end_of_directory_not_reached = 0;
978
        uint16_t        end_of_directory_not_reached = 0;
979
        uint8_t         i                       = 0;
979
        uint8_t         i                       = 0;
980
        uint8_t         retvalue        = 0;
980
        uint8_t         retvalue        = 0;
981
        DirEntry_t*     dir;
981
        DirEntry_t*     dir;
982
 
982
 
983
        if((!Partition.IsValid) || (file == NULL) || (dirname == NULL)) return (retvalue);
983
        if((!Partition.IsValid) || (file == NULL) || (dirname == NULL)) return (retvalue);
984
        // It is not checked here that the dir entry that should be created is already existent!
984
        // It is not checked here that the dir entry that should be created is already existent!
985
 
985
 
986
        // Dir entries can be created only in file-clusters that have
986
        // Dir entries can be created only in file-clusters that have
987
        // the dir-flag set in its attribute or within the root directory
987
        // the dir-flag set in its attribute or within the root directory
988
 
988
 
989
        file->FirstSectorOfFirstCluster = 0;
989
        file->FirstSectorOfFirstCluster = 0;
990
        // no current directory exist therefore assume creating in the root
990
        // no current directory exist therefore assume creating in the root
991
        if(file->DirectorySector == 0)
991
        if(file->DirectorySector == 0)
992
        {
992
        {
993
                max_dir_sector = (Partition.MaxRootEntries * DIRENTRY_SIZE)/BYTES_PER_SECTOR;
993
                max_dir_sector = (Partition.MaxRootEntries * DIRENTRY_SIZE)/BYTES_PER_SECTOR;
994
                dircluster = 0;
994
                dircluster = 0;
995
                file->FirstSectorOfFirstCluster = Partition.FirstRootDirSector;
995
                file->FirstSectorOfFirstCluster = Partition.FirstRootDirSector;
996
        }
996
        }
997
        // within the root directory area we can read sectors sequentially until the end of this area
997
        // within the root directory area we can read sectors sequentially until the end of this area
998
        else if((Partition.FirstRootDirSector <= file->DirectorySector) && (file->DirectorySector < Partition.FirstDataSector))
998
        else if((Partition.FirstRootDirSector <= file->DirectorySector) && (file->DirectorySector < Partition.FirstDataSector))
999
        {
999
        {
1000
                max_dir_sector = (Partition.MaxRootEntries * DIRENTRY_SIZE)/BYTES_PER_SECTOR;
1000
                max_dir_sector = (Partition.MaxRootEntries * DIRENTRY_SIZE)/BYTES_PER_SECTOR;
1001
        }
1001
        }
1002
        // within the data clusters we can read sectors sequentially only within the cluster
1002
        // within the data clusters we can read sectors sequentially only within the cluster
1003
        else if((Partition.FirstDataSector <= file->DirectorySector) && (file->DirectorySector <= Partition.LastDataSector))
1003
        else if((Partition.FirstDataSector <= file->DirectorySector) && (file->DirectorySector <= Partition.LastDataSector))
1004
        {
1004
        {
1005
                max_dir_sector = Partition.SectorsPerCluster;
1005
                max_dir_sector = Partition.SectorsPerCluster;
1006
        }
1006
        }
1007
        else return (retvalue); // bad sector range for directory sector of the file
1007
        else return (retvalue); // bad sector range for directory sector of the file
1008
        // if search area is not defined yet
1008
        // if search area is not defined yet
1009
        if(file->FirstSectorOfFirstCluster == 0)
1009
        if(file->FirstSectorOfFirstCluster == 0)
1010
        {
1010
        {
1011
            // check if the directory entry of current file is existent and has the dir-flag set
1011
            // check if the directory entry of current file is existent and has the dir-flag set
1012
                file->SectorInCache = file->DirectorySector;                            // update the sector number of file cache.
1012
                file->SectorInCache = file->DirectorySector;                            // update the sector number of file cache.
1013
                if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector.
1013
                if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector.
1014
                {
1014
                {
1015
                        Fat16_Deinit();
1015
                        Fat16_Deinit();
1016
                        return(retvalue);
1016
                        return(retvalue);
1017
                }
1017
                }
1018
                dir = (DirEntry_t *)file->Cache;                                                        // set pointer to directory
1018
                dir = (DirEntry_t *)file->Cache;                                                        // set pointer to directory
1019
                switch((uint8_t)dir[file->DirectoryIndex].Name[0])                                      // check if current directory exist
1019
                switch((uint8_t)dir[file->DirectoryIndex].Name[0])                                      // check if current directory exist
1020
                {
1020
                {
1021
                        case SLOT_EMPTY:
1021
                        case SLOT_EMPTY:
1022
                        case SLOT_DELETED:
1022
                        case SLOT_DELETED:
1023
                                return (retvalue);
1023
                                return (retvalue);
1024
                                break;
1024
                                break;
1025
                        default:        // and is a real directory
1025
                        default:        // and is a real directory
1026
                                if((dir[file->DirectoryIndex].Attribute & ATTR_SUBDIRECTORY) != ATTR_SUBDIRECTORY)
1026
                                if((dir[file->DirectoryIndex].Attribute & ATTR_SUBDIRECTORY) != ATTR_SUBDIRECTORY)
1027
                                {       // current file is not a directory therefore no file or subdirectory can be created here
1027
                                {       // current file is not a directory therefore no file or subdirectory can be created here
1028
                                        return (retvalue);
1028
                                        return (retvalue);
1029
                                }
1029
                                }
1030
                                break;
1030
                                break;
1031
                }
1031
                }
1032
                dircluster = dir[file->DirectoryIndex].StartCluster;
1032
                dircluster = dir[file->DirectoryIndex].StartCluster;
1033
                file->FirstSectorOfFirstCluster = Fat16ClusterToSector(dircluster);
1033
                file->FirstSectorOfFirstCluster = Fat16ClusterToSector(dircluster);
1034
        }
1034
        }
1035
 
1035
 
1036
        subdircluster = FindNextFreeCluster(file);      // get the next free cluster on the disk and mark it as used.
1036
        subdircluster = FindNextFreeCluster(file);      // get the next free cluster on the disk and mark it as used.
1037
        if(subdircluster)
1037
        if(subdircluster)
1038
        {
1038
        {
1039
                file->FirstSectorOfCurrCluster  = file->FirstSectorOfFirstCluster;
1039
                file->FirstSectorOfCurrCluster  = file->FirstSectorOfFirstCluster;
1040
                file->SectorOfCurrCluster               = 0;
1040
                file->SectorOfCurrCluster               = 0;
1041
                do // loop over all clusters of current directory
1041
                do // loop over all clusters of current directory
1042
                {
1042
                {
1043
                        dir_sector = 0; // reset sector counter within a new cluster
1043
                        dir_sector = 0; // reset sector counter within a new cluster
1044
                        do // loop over all sectors of a cluster or all sectors of the root directory
1044
                        do // loop over all sectors of a cluster or all sectors of the root directory
1045
                        {
1045
                        {
1046
                                curr_sector = file->FirstSectorOfCurrCluster + dir_sector;      // calculate sector number
1046
                                curr_sector = file->FirstSectorOfCurrCluster + dir_sector;      // calculate sector number
1047
                                file->SectorInCache = curr_sector;                                                      // upate the sector number of file cache.
1047
                                file->SectorInCache = curr_sector;                                                      // upate the sector number of file cache.
1048
                                if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector.
1048
                                if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector.
1049
                                {
1049
                                {
1050
                                        Fat16_Deinit();
1050
                                        Fat16_Deinit();
1051
                                        return(retvalue);
1051
                                        return(retvalue);
1052
                                }
1052
                                }
1053
                                dir = (DirEntry_t *)file->Cache;                                                        // set pointer to directory
1053
                                dir = (DirEntry_t *)file->Cache;                                                        // set pointer to directory
1054
                                // search all directory entries of a sector
1054
                                // search all directory entries of a sector
1055
                                for(dir_entry = 0; dir_entry < DIRENTRIES_PER_SECTOR; dir_entry++)
1055
                                for(dir_entry = 0; dir_entry < DIRENTRIES_PER_SECTOR; dir_entry++)
1056
                                {       // check if current direntry is available
1056
                                {       // check if current direntry is available
1057
                                        if(((uint8_t)dir[dir_entry].Name[0] == SLOT_EMPTY) || ((uint8_t)dir[dir_entry].Name[0] == SLOT_DELETED))
1057
                                        if(((uint8_t)dir[dir_entry].Name[0] == SLOT_EMPTY) || ((uint8_t)dir[dir_entry].Name[0] == SLOT_DELETED))
1058
                                        {       // a free direntry was found
1058
                                        {       // a free direntry was found
1059
                                                for(i = 0; i < 11; i++) dir[dir_entry].Name[i] = dirname[i];            // Set dir name
1059
                                                for(i = 0; i < 11; i++) dir[dir_entry].Name[i] = dirname[i];            // Set dir name
1060
                                                dir[dir_entry].Attribute    = attrib;                                                           // Set the attribute of the new directoryentry.
1060
                                                dir[dir_entry].Attribute    = attrib;                                                           // Set the attribute of the new directoryentry.
1061
                                                dir[dir_entry].StartCluster = subdircluster;                                            // copy the location of the first datacluster to the directoryentry.
1061
                                                dir[dir_entry].StartCluster = subdircluster;                                            // copy the location of the first datacluster to the directoryentry.
1062
                                                dir[dir_entry].DateTime         = FileDateTime(&SystemTime);                    // set date/time
1062
                                                dir[dir_entry].DateTime         = FileDateTime(&SystemTime);                    // set date/time
1063
                                                dir[dir_entry].Size             = 0;                                                                    // the new createted file has no content yet.
1063
                                                dir[dir_entry].Size             = 0;                                                                    // the new createted file has no content yet.
1064
                                                if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))       // write back to card
1064
                                                if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))       // write back to card
1065
                                                {
1065
                                                {
1066
                                                        Fat16_Deinit();
1066
                                                        Fat16_Deinit();
1067
                                                        return(retvalue);
1067
                                                        return(retvalue);
1068
                                                }
1068
                                                }
1069
                                                file->FirstSectorOfFirstCluster = Fat16ClusterToSector(subdircluster);  // Calculate absolute sectorposition of first datacluster.
1069
                                                file->FirstSectorOfFirstCluster = Fat16ClusterToSector(subdircluster);  // Calculate absolute sectorposition of first datacluster.
1070
                                                file->FirstSectorOfCurrCluster  = file->FirstSectorOfFirstCluster;      // Start reading the file with the first sector of the first datacluster.
1070
                                                file->FirstSectorOfCurrCluster  = file->FirstSectorOfFirstCluster;      // Start reading the file with the first sector of the first datacluster.
1071
                                                file->SectorOfCurrCluster               = 0;                                                            // reset sector of cureen cluster
1071
                                                file->SectorOfCurrCluster               = 0;                                                            // reset sector of cureen cluster
1072
                                                file->ByteOfCurrSector                  = 0;                                                            // reset the byte location within the current sector
1072
                                                file->ByteOfCurrSector                  = 0;                                                            // reset the byte location within the current sector
1073
                                                file->Attribute                                 = attrib;                                               // set file attribute to dir attribute
1073
                                                file->Attribute                                 = attrib;                                               // set file attribute to dir attribute
1074
                                                file->Size                                              = 0;                                                        // new file has no size
1074
                                                file->Size                                              = 0;                                                        // new file has no size
1075
                                                file->DirectorySector                   = curr_sector;
1075
                                                file->DirectorySector                   = curr_sector;
1076
                                                file->DirectoryIndex                    = dir_entry;
1076
                                                file->DirectoryIndex                    = dir_entry;
1077
                                                if((attrib & ATTR_SUBDIRECTORY) == ATTR_SUBDIRECTORY)                           // if a new directory was created then initilize the data area
1077
                                                if((attrib & ATTR_SUBDIRECTORY) == ATTR_SUBDIRECTORY)                           // if a new directory was created then initilize the data area
1078
                                                {
1078
                                                {
1079
                                                        ClearCurrCluster(file); // fill cluster with zeros
1079
                                                        ClearCurrCluster(file); // fill cluster with zeros
1080
                                                        file->SectorInCache = file->FirstSectorOfFirstCluster;
1080
                                                        file->SectorInCache = file->FirstSectorOfFirstCluster;
1081
                                                        if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector.
1081
                                                        if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))// read in the sector.
1082
                                                        {
1082
                                                        {
1083
                                                                Fat16_Deinit();
1083
                                                                Fat16_Deinit();
1084
                                                                return(retvalue);
1084
                                                                return(retvalue);
1085
                                                        }
1085
                                                        }
1086
                                                        dir = (DirEntry_t *)file->Cache;
1086
                                                        dir = (DirEntry_t *)file->Cache;
1087
                                                        // create direntry "." to current dir
1087
                                                        // create direntry "." to current dir
1088
                                                        dir[0].Name[0] = 0x2E;
1088
                                                        dir[0].Name[0] = 0x2E;
1089
                                                        for(i = 1; i < 11; i++) dir[0].Name[i] = ' ';
1089
                                                        for(i = 1; i < 11; i++) dir[0].Name[i] = ' ';
1090
                                                        dir[0].Attribute = ATTR_SUBDIRECTORY;
1090
                                                        dir[0].Attribute = ATTR_SUBDIRECTORY;
1091
                                                        dir[0].StartCluster = subdircluster;
1091
                                                        dir[0].StartCluster = subdircluster;
1092
                                                        dir[0].DateTime = 0;
1092
                                                        dir[0].DateTime = 0;
1093
                                                        dir[0].Size = 0;
1093
                                                        dir[0].Size = 0;
1094
                                                        // create direntry ".." to the upper dir
1094
                                                        // create direntry ".." to the upper dir
1095
                                                        dir[1].Name[0] = 0x2E;
1095
                                                        dir[1].Name[0] = 0x2E;
1096
                                                        dir[1].Name[1] = 0x2E;
1096
                                                        dir[1].Name[1] = 0x2E;
1097
                                                        for(i = 2; i < 11; i++) dir[1].Name[i] = ' ';
1097
                                                        for(i = 2; i < 11; i++) dir[1].Name[i] = ' ';
1098
                                                        dir[1].Attribute = ATTR_SUBDIRECTORY;
1098
                                                        dir[1].Attribute = ATTR_SUBDIRECTORY;
1099
                                                        dir[1].StartCluster = dircluster;
1099
                                                        dir[1].StartCluster = dircluster;
1100
                                                        dir[1].DateTime = 0;
1100
                                                        dir[1].DateTime = 0;
1101
                                                        dir[1].Size = 0;
1101
                                                        dir[1].Size = 0;
1102
                                                        if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))// read in the sector.
1102
                                                        if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))// read in the sector.
1103
                                                        {
1103
                                                        {
1104
                                                                Fat16_Deinit();
1104
                                                                Fat16_Deinit();
1105
                                                                return(retvalue);
1105
                                                                return(retvalue);
1106
                                                        }
1106
                                                        }
1107
                                                }
1107
                                                }
1108
                                                retvalue = 1;
1108
                                                retvalue = 1;
1109
                                                dir_entry = DIRENTRIES_PER_SECTOR;      // stop for-loop
1109
                                                dir_entry = DIRENTRIES_PER_SECTOR;      // stop for-loop
1110
                                        }
1110
                                        }
1111
                                }
1111
                                }
1112
                                dir_sector++; // search next sector
1112
                                dir_sector++; // search next sector
1113
                        // stop if we reached the end of the cluster or the end of the root dir
1113
                        // stop if we reached the end of the cluster or the end of the root dir
1114
                        }while((dir_sector < max_dir_sector) && (!retvalue));
1114
                        }while((dir_sector < max_dir_sector) && (!retvalue));
1115
 
1115
 
1116
                        // if we are seaching in the data area and the file not found in this cluster so take next cluster.
1116
                        // if we are seaching in the data area and the file not found in this cluster so take next cluster.
1117
                        if(!retvalue && ( Partition.FirstDataSector <= file->FirstSectorOfCurrCluster))
1117
                        if(!retvalue && ( Partition.FirstDataSector <= file->FirstSectorOfCurrCluster))
1118
                        {
1118
                        {
1119
                                end_of_directory_not_reached = GetNextCluster(file);  // updates File->FirstSectorOfCurrCluster
1119
                                end_of_directory_not_reached = GetNextCluster(file);  // updates File->FirstSectorOfCurrCluster
1120
                        }
1120
                        }
1121
                }while((end_of_directory_not_reached) && (!retvalue));
1121
                }while((end_of_directory_not_reached) && (!retvalue));
1122
                // Perhaps we are at the end of the last cluster of a directory file an have no free direntry found.
1122
                // Perhaps we are at the end of the last cluster of a directory file an have no free direntry found.
1123
                // Then we would need to add a cluster to that file and create the new direntry there.
1123
                // Then we would need to add a cluster to that file and create the new direntry there.
1124
                // This code is not implemented yet, because its occurs only if more that 32*32=1024 direntries are
1124
                // This code is not implemented yet, because its occurs only if more that 32*32=1024 direntries are
1125
                // within a subdirectory of root.
1125
                // within a subdirectory of root.
1126
        }
1126
        }
1127
        return(retvalue);       // return 1 if file has been created otherwise return 0.
1127
        return(retvalue);       // return 1 if file has been created otherwise return 0.
1128
}
1128
}
1129
 
1129
 
1130
/********************************************************************************************************************************************/
1130
/********************************************************************************************************************************************/
1131
/*      Function:               FileExist(const int8_t* filename, uint8_t attribfilter, uint8_t attribmask, File_t *file);                                                                                      */
1131
/*      Function:               FileExist(const int8_t* filename, uint8_t attribfilter, uint8_t attribmask, File_t *file);                                                                                      */
1132
/*                                                                                                                                                                                                                                                                                      */
1132
/*                                                                                                                                                                                                                                                                                      */
1133
/*      Description:    This function looks for the specified file including its subdirectories beginning                                                                               */
1133
/*      Description:    This function looks for the specified file including its subdirectories beginning                                                                               */
1134
/*                                      in the rootdirectory of the drive. If the file is found the Filepointer properties are                                                                  */
1134
/*                                      in the rootdirectory of the drive. If the file is found the Filepointer properties are                                                                  */
1135
/*                                      updated.                                                                                                                                                                                                                                */
1135
/*                                      updated.                                                                                                                                                                                                                                */
1136
/*                                                                                                                                                                                                                                                                                      */
1136
/*                                                                                                                                                                                                                                                                                      */
1137
/*      Returnvalue:    1 if file is found else 0.                                                                                                                                                                                              */
1137
/*      Returnvalue:    1 if file is found else 0.                                                                                                                                                                                              */
1138
/********************************************************************************************************************************************/
1138
/********************************************************************************************************************************************/
1139
uint8_t FileExist(const int8_t* filename, const uint8_t attribfilter, const uint8_t attribmask, File_t *file)
1139
uint8_t FileExist(const int8_t* filename, const uint8_t attribfilter, const uint8_t attribmask, File_t *file)
1140
{
1140
{
1141
        int8_t* path = 0;
1141
        int8_t* path = 0;
1142
        int8_t* subpath = 0;
1142
        int8_t* subpath = 0;
1143
        uint8_t af, am, file_exist = 0;
1143
        uint8_t af, am, file_exist = 0;
1144
        int8_t  dirname[12]; // 8+3 + temination character
1144
        int8_t  dirname[12]; // 8+3 + temination character
1145
 
1145
 
1146
        // if incomming pointers are useless return immediatly
1146
        // if incomming pointers are useless return immediatly
1147
        if ((filename == NULL) || (file == NULL) || (!Partition.IsValid)) return 0;
1147
        if ((filename == NULL) || (file == NULL) || (!Partition.IsValid)) return 0;
1148
 
1148
 
1149
        // trace along the filepath
1149
        // trace along the filepath
1150
        path = (int8_t*)filename;                                                               // start a the beginning of the filename string
1150
        path = (int8_t*)filename;                                                               // start a the beginning of the filename string
1151
        file->DirectorySector = 0;                                                              // start at RootDirectory with file search
1151
        file->DirectorySector = 0;                                                              // start at RootDirectory with file search
1152
        file->DirectoryIndex = 0;
1152
        file->DirectoryIndex = 0;
1153
        // as long as the file was not found and the remaining path is not empty
1153
        // as long as the file was not found and the remaining path is not empty
1154
        while((*path != 0) && !file_exist)
1154
        while((*path != 0) && !file_exist)
1155
        {       // separate dirname and subpath from filepath string
1155
        {       // separate dirname and subpath from filepath string
1156
                subpath = SeperateDirName(path, dirname);
1156
                subpath = SeperateDirName(path, dirname);
1157
                if(subpath != NULL)
1157
                if(subpath != NULL)
1158
                {
1158
                {
1159
                        if(*subpath == 0)
1159
                        if(*subpath == 0)
1160
                        {       // empty subpath indicates last element of dir chain
1160
                        {       // empty subpath indicates last element of dir chain
1161
                                af = attribfilter;
1161
                                af = attribfilter;
1162
                                am = attribmask;
1162
                                am = attribmask;
1163
                        }
1163
                        }
1164
                        else  // it must be a subdirectory and no volume label
1164
                        else  // it must be a subdirectory and no volume label
1165
                        {
1165
                        {
1166
                                af = ATTR_SUBDIRECTORY;
1166
                                af = ATTR_SUBDIRECTORY;
1167
                                am = ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL;
1167
                                am = ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL;
1168
                        }
1168
                        }
1169
                        if(!DirectoryEntryExist(dirname, af, am, file))
1169
                        if(!DirectoryEntryExist(dirname, af, am, file))
1170
                        {
1170
                        {
1171
                                return (file_exist); // subdirectory does not exist
1171
                                return (file_exist); // subdirectory does not exist
1172
                        }
1172
                        }
1173
                        else
1173
                        else
1174
                        {
1174
                        {
1175
                                if (*subpath == 0)
1175
                                if (*subpath == 0)
1176
                                {
1176
                                {
1177
                                        file_exist = 1; // last element of path chain was found with the given attribute filter
1177
                                        file_exist = 1; // last element of path chain was found with the given attribute filter
1178
                                }
1178
                                }
1179
                        }
1179
                        }
1180
                }
1180
                }
1181
                else // error seperating the subpath
1181
                else // error seperating the subpath
1182
                {
1182
                {
1183
                        return file_exist; // bad subdir format
1183
                        return file_exist; // bad subdir format
1184
                }
1184
                }
1185
                path = subpath;
1185
                path = subpath;
1186
                subpath = 0;
1186
                subpath = 0;
1187
        }
1187
        }
1188
        return (file_exist);
1188
        return (file_exist);
1189
}
1189
}
1190
 
1190
 
1191
 
1191
 
1192
/********************************************************************************************************************************************/
1192
/********************************************************************************************************************************************/
1193
/*      Function:               FileCreate(const s8* filename, u8 attrib, File_t *file);                                                                                                                                */
1193
/*      Function:               FileCreate(const s8* filename, u8 attrib, File_t *file);                                                                                                                                */
1194
/*                                                                                                                                                                                                                                                                                      */
1194
/*                                                                                                                                                                                                                                                                                      */
1195
/*      Description:    This function looks for the specified file including its subdirectories beginning                                                                               */
1195
/*      Description:    This function looks for the specified file including its subdirectories beginning                                                                               */
1196
/*                                      in the rootdirectory of the partition. If the file is found the Filepointer properties are                                                              */
1196
/*                                      in the rootdirectory of the partition. If the file is found the Filepointer properties are                                                              */
1197
/*                                      updated. If file or its subdirectories are not found they will be created                                                                                               */
1197
/*                                      updated. If file or its subdirectories are not found they will be created                                                                                               */
1198
/*                                                                                                                                                                                                                                                                                      */
1198
/*                                                                                                                                                                                                                                                                                      */
1199
/*      Returnvalue:    1 if file was created else 0.                                                                                                                                                                                   */
1199
/*      Returnvalue:    1 if file was created else 0.                                                                                                                                                                                   */
1200
/********************************************************************************************************************************************/
1200
/********************************************************************************************************************************************/
1201
uint8_t FileCreate(const int8_t* filename, const uint8_t attrib, File_t *file)
1201
uint8_t FileCreate(const int8_t* filename, const uint8_t attrib, File_t *file)
1202
{
1202
{
1203
        int8_t *path = 0;
1203
        int8_t *path = 0;
1204
        int8_t *subpath = 0;
1204
        int8_t *subpath = 0;
1205
        uint8_t af, am, file_created = 0;
1205
        uint8_t af, am, file_created = 0;
1206
        int8_t dirname[12];
1206
        int8_t dirname[12];
1207
 
1207
 
1208
        // if incomming pointers are useless return immediatly
1208
        // if incomming pointers are useless return immediatly
1209
        if ((filename == NULL) || (file == NULL) || (!Partition.IsValid)) return 0;
1209
        if ((filename == NULL) || (file == NULL) || (!Partition.IsValid)) return 0;
1210
 
1210
 
1211
        // trace along the filepath
1211
        // trace along the filepath
1212
        path = (int8_t*)filename;                                                                       // start a the beginning of the filename string
1212
        path = (int8_t*)filename;                                                                       // start a the beginning of the filename string
1213
        file->DirectorySector = 0;                                                              // start at RootDirectory with file search
1213
        file->DirectorySector = 0;                                                              // start at RootDirectory with file search
1214
        file->DirectoryIndex = 0;
1214
        file->DirectoryIndex = 0;
1215
        // as long as the file was not created and the remaining file path is not empty
1215
        // as long as the file was not created and the remaining file path is not empty
1216
        while((*path != 0) && !file_created)
1216
        while((*path != 0) && !file_created)
1217
        {   // separate dirname and subpath from filepath string
1217
        {   // separate dirname and subpath from filepath string
1218
                subpath = SeperateDirName(path, dirname);
1218
                subpath = SeperateDirName(path, dirname);
1219
                if(subpath != NULL)
1219
                if(subpath != NULL)
1220
                {
1220
                {
1221
                        if(*subpath == 0)
1221
                        if(*subpath == 0)
1222
                        {       // empty subpath indicates last element of dir chain
1222
                        {       // empty subpath indicates last element of dir chain
1223
                                af = ATTR_NONE;
1223
                                af = ATTR_NONE;
1224
                                am = ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL;  // any file that is no subdir or volume label
1224
                                am = ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL;  // any file that is no subdir or volume label
1225
                        }
1225
                        }
1226
                        else  // it must be a subdirectory and no volume label
1226
                        else  // it must be a subdirectory and no volume label
1227
                        {
1227
                        {
1228
                                af = ATTR_SUBDIRECTORY;
1228
                                af = ATTR_SUBDIRECTORY;
1229
                                am = ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL;
1229
                                am = ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL;
1230
                        }
1230
                        }
1231
                        if(!DirectoryEntryExist(dirname, af, am, file)) // if subdir or file is not existent
1231
                        if(!DirectoryEntryExist(dirname, af, am, file)) // if subdir or file is not existent
1232
                        {  // try to create subdir or file
1232
                        {  // try to create subdir or file
1233
                                if(*subpath == 0) af = attrib; // if last element in dir chain take the given attribute
1233
                                if(*subpath == 0) af = attrib; // if last element in dir chain take the given attribute
1234
                                if(!CreateDirectoryEntry(dirname, af, file))
1234
                                if(!CreateDirectoryEntry(dirname, af, file))
1235
                                {       // could not be created
1235
                                {       // could not be created
1236
                                        return(file_created);
1236
                                        return(file_created);
1237
                                }
1237
                                }
1238
                                else if (*subpath == 0) file_created = 1; // last element of path chain was created
1238
                                else if (*subpath == 0) file_created = 1; // last element of path chain was created
1239
                        }
1239
                        }
1240
                }
1240
                }
1241
                else // error seperating the subpath
1241
                else // error seperating the subpath
1242
                {
1242
                {
1243
                        return file_created; // bad subdir format
1243
                        return file_created; // bad subdir format
1244
                }
1244
                }
1245
                path = subpath;
1245
                path = subpath;
1246
                subpath = 0;
1246
                subpath = 0;
1247
        }
1247
        }
1248
        return (file_created);
1248
        return (file_created);
1249
}
1249
}
1250
 
1250
 
1251
 
1251
 
1252
/********************************************************************************************************************************************/
1252
/********************************************************************************************************************************************/
1253
/*      Function:               File_t * fopen_(int8_t* filename, int8_t mode);                                                                                                                                                                 */
1253
/*      Function:               File_t * fopen_(int8_t* filename, int8_t mode);                                                                                                                                                                 */
1254
/*                                                                                                                                                                                                                                                                                      */
1254
/*                                                                                                                                                                                                                                                                                      */
1255
/*      Description:    This function looks for the specified file in the rootdirectory of the drive. If the file is found the number of the    */
1255
/*      Description:    This function looks for the specified file in the rootdirectory of the drive. If the file is found the number of the    */
1256
/*                                      corrosponding filepointer is returned. Only modes 'r' (reading) and 'a' append are implemented yet.                                             */
1256
/*                                      corrosponding filepointer is returned. Only modes 'r' (reading) and 'a' append are implemented yet.                                             */
1257
/*                                                                                                                                                                                                                                                                                      */
1257
/*                                                                                                                                                                                                                                                                                      */
1258
/*      Returnvalue:    The filepointer to the file or 0 if faild.                                                                                                                                                              */
1258
/*      Returnvalue:    The filepointer to the file or 0 if faild.                                                                                                                                                              */
1259
/********************************************************************************************************************************************/
1259
/********************************************************************************************************************************************/
1260
File_t * fopen_(int8_t * const filename, const int8_t mode)
1260
File_t * fopen_(int8_t * const filename, const int8_t mode)
1261
{
1261
{
1262
        File_t *file    = 0;
1262
        File_t *file    = 0;
1263
 
1263
 
1264
        if((!Partition.IsValid) || (filename == 0)) return(file);
1264
        if((!Partition.IsValid) || (filename == 0)) return(file);
1265
 
1265
 
1266
        // Look for an unused filepointer in the file pointer list?
1266
        // Look for an unused filepointer in the file pointer list?
1267
        file = LockFilePointer();
1267
        file = LockFilePointer();
1268
        // if no unused file pointer was found return 0
1268
        // if no unused file pointer was found return 0
1269
        if(file == NULL) return(file);
1269
        if(file == NULL) return(file);
1270
 
1270
 
1271
        // now we have found a free filepointer and claimed it
1271
        // now we have found a free filepointer and claimed it
1272
        // so let initiate its property values
1272
        // so let initiate its property values
1273
        file->FirstSectorOfFirstCluster = 0;            // Sectorpointer to the first sector of the first datacluster of the file.
1273
        file->FirstSectorOfFirstCluster = 0;            // Sectorpointer to the first sector of the first datacluster of the file.
1274
        file->FirstSectorOfCurrCluster  = 0;            // Pointer to the cluster which is edited at the moment.
1274
        file->FirstSectorOfCurrCluster  = 0;            // Pointer to the cluster which is edited at the moment.
1275
        file->SectorOfCurrCluster               = 0;            // The sector which is edited at the moment (cluster_pointer + sector_index).
1275
        file->SectorOfCurrCluster               = 0;            // The sector which is edited at the moment (cluster_pointer + sector_index).
1276
        file->ByteOfCurrSector                  = 0;            // The bytelocation within the current sector (cluster_pointer + sector_index + byte_index).
1276
        file->ByteOfCurrSector                  = 0;            // The bytelocation within the current sector (cluster_pointer + sector_index + byte_index).
1277
        file->Mode                                              = mode;         // mode of fileoperation (read,write)
1277
        file->Mode                                              = mode;         // mode of fileoperation (read,write)
1278
        file->Size                                              = 0;            // the size of the opened file in bytes.
1278
        file->Size                                              = 0;            // the size of the opened file in bytes.
1279
        file->Position                                  = 0;            // pointer to a byte within the file 0 < fileposition < filesize
1279
        file->Position                                  = 0;            // pointer to a byte within the file 0 < fileposition < filesize
1280
        file->SectorInCache                             = 0;            // the last sector read, wich is still in the sectorbuffer.
1280
        file->SectorInCache                             = 0;            // the last sector read, wich is still in the sectorbuffer.
1281
        file->DirectorySector                   = 0;            // the sectorposition where the directoryentry has been made.
1281
        file->DirectorySector                   = 0;            // the sectorposition where the directoryentry has been made.
1282
        file->DirectoryIndex                    = 0;            // the index to the directoryentry within the specified sector.
1282
        file->DirectoryIndex                    = 0;            // the index to the directoryentry within the specified sector.
1283
        file->Attribute                                 = 0;            // the attribute of the file opened.
1283
        file->Attribute                                 = 0;            // the attribute of the file opened.
1284
 
1284
 
1285
        // check if a real file (no directory) to the given filename exist
1285
        // check if a real file (no directory) to the given filename exist
1286
        if(FileExist(filename, ATTR_NONE, ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL, file))
1286
        if(FileExist(filename, ATTR_NONE, ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL, file))
1287
        {  // file exist
1287
        {  // file exist
1288
                switch(mode)  // check mode
1288
                switch(mode)  // check mode
1289
                {
1289
                {
1290
                        case 'a':       // if mode is: append to file
1290
                        case 'a':       // if mode is: append to file
1291
                                if((file->Attribute & ATTR_READONLY) == ATTR_READONLY)
1291
                                if((file->Attribute & ATTR_READONLY) == ATTR_READONLY)
1292
                                {       // file is marked as readonly --> do not open this file
1292
                                {       // file is marked as readonly --> do not open this file
1293
                                        fclose_(file);
1293
                                        fclose_(file);
1294
                                        file = NULL;
1294
                                        file = NULL;
1295
                                }
1295
                                }
1296
                                else
1296
                                else
1297
                                {       // file is not marked as read only --> goto end of file
1297
                                {       // file is not marked as read only --> goto end of file
1298
                                        fseek_(file, 0, SEEK_END);              // point to the end of the file
1298
                                        fseek_(file, 0, SEEK_END);              // point to the end of the file
1299
                                }
1299
                                }
1300
                                break;
1300
                                break;
1301
                        case 'w':       // if mode is: write to file
1301
                        case 'w':       // if mode is: write to file
1302
                                if((file->Attribute & ATTR_READONLY) == ATTR_READONLY)
1302
                                if((file->Attribute & ATTR_READONLY) == ATTR_READONLY)
1303
                                {       // file is marked as readonly --> do not open this file
1303
                                {       // file is marked as readonly --> do not open this file
1304
                                        fclose_(file);
1304
                                        fclose_(file);
1305
                                        file = NULL;
1305
                                        file = NULL;
1306
                                }
1306
                                }
1307
                                else
1307
                                else
1308
                                {       // file is not marked as read only --> goto start of file
1308
                                {       // file is not marked as read only --> goto start of file
1309
                                        // free all clusters of that file
1309
                                        // free all clusters of that file
1310
                                        DeleteClusterChain(SectorToFat16Cluster(file->FirstSectorOfFirstCluster));
1310
                                        DeleteClusterChain(SectorToFat16Cluster(file->FirstSectorOfFirstCluster));
1311
                                        // mar an empy cluster as the last one and store the corresponding sector
1311
                                        // mar an empy cluster as the last one and store the corresponding sector
1312
                                        file->FirstSectorOfFirstCluster = Fat16ClusterToSector(FindNextFreeCluster(file));
1312
                                        file->FirstSectorOfFirstCluster = Fat16ClusterToSector(FindNextFreeCluster(file));
1313
                                        file->FirstSectorOfCurrCluster = file->FirstSectorOfFirstCluster;
1313
                                        file->FirstSectorOfCurrCluster = file->FirstSectorOfFirstCluster;
1314
                                        file->SectorOfCurrCluster = 0;
1314
                                        file->SectorOfCurrCluster = 0;
1315
                                        file->ByteOfCurrSector = 0;
1315
                                        file->ByteOfCurrSector = 0;
1316
                                        file->Size = 0;
1316
                                        file->Size = 0;
1317
                                        file->Position = 0;
1317
                                        file->Position = 0;
1318
                                        fseek_(file, 0, SEEK_SET);
1318
                                        fseek_(file, 0, SEEK_SET);
1319
                                }
1319
                                }
1320
                                break;
1320
                                break;
1321
                        case 'r':       // if mode is: read from file
1321
                        case 'r':       // if mode is: read from file
1322
                                // goto end of file
1322
                                // goto end of file
1323
                                fseek_(file, 0, SEEK_SET);
1323
                                fseek_(file, 0, SEEK_SET);
1324
                                break;
1324
                                break;
1325
                        default: // other modes are not supported
1325
                        default: // other modes are not supported
1326
                                fclose_(file);
1326
                                fclose_(file);
1327
                                file = NULL;
1327
                                file = NULL;
1328
                        break;
1328
                        break;
1329
                }
1329
                }
1330
                return(file);
1330
                return(file);
1331
        }
1331
        }
1332
        else // file does not exist
1332
        else // file does not exist
1333
        {
1333
        {
1334
                switch(mode)  // check mode
1334
                switch(mode)  // check mode
1335
                {
1335
                {
1336
                        case 'a':
1336
                        case 'a':
1337
                        case 'w': // if mode is write or append
1337
                        case 'w': // if mode is write or append
1338
                                // try to create the file
1338
                                // try to create the file
1339
                                if(!FileCreate(filename, ATTR_ARCHIVE, file))
1339
                                if(!FileCreate(filename, ATTR_ARCHIVE, file))
1340
                                { // if it could not be created
1340
                                { // if it could not be created
1341
                                        fclose_(file);
1341
                                        fclose_(file);
1342
                                        file = NULL;
1342
                                        file = NULL;
1343
                                }
1343
                                }
1344
                                break;
1344
                                break;
1345
                        case 'r': // else opened for 'r'
1345
                        case 'r': // else opened for 'r'
1346
                        default:  // of unsupported mode
1346
                        default:  // of unsupported mode
1347
                                fclose_(file);
1347
                                fclose_(file);
1348
                                file = NULL;
1348
                                file = NULL;
1349
                                break;
1349
                                break;
1350
                }
1350
                }
1351
                return(file);
1351
                return(file);
1352
        }
1352
        }
1353
        // we should never come to this point
1353
        // we should never come to this point
1354
        fclose_(file);
1354
        fclose_(file);
1355
        file = NULL;
1355
        file = NULL;
1356
        return(file);
1356
        return(file);
1357
}
1357
}
1358
 
1358
 
1359
/****************************************************************************************************************************************************/
1359
/****************************************************************************************************************************************************/
1360
/* Function:    fflush_(File *);                                                                                                                                                                                                                                        */
1360
/* Function:    fflush_(File *);                                                                                                                                                                                                                                        */
1361
/*                                                                                                                                                                                                                                                                                                      */
1361
/*                                                                                                                                                                                                                                                                                                      */
1362
/* Description: This function writes the data already in the buffer but not yet written to the file.                                                                                            */
1362
/* Description: This function writes the data already in the buffer but not yet written to the file.                                                                                            */
1363
/*                                                                                                                                                                                                                                                                                                      */
1363
/*                                                                                                                                                                                                                                                                                                      */
1364
/* Returnvalue: 0 on success EOF on error                                                                                                                                                                                                                       */
1364
/* Returnvalue: 0 on success EOF on error                                                                                                                                                                                                                       */
1365
/****************************************************************************************************************************************************/
1365
/****************************************************************************************************************************************************/
1366
int16_t fflush_(File_t * const file)
1366
int16_t fflush_(File_t * const file)
1367
{
1367
{
1368
        DirEntry_t *dir;
1368
        DirEntry_t *dir;
1369
 
1369
 
1370
        if((file == NULL) || (!Partition.IsValid)) return (EOF);
1370
        if((file == NULL) || (!Partition.IsValid)) return (EOF);
1371
 
1371
 
1372
        switch(file->Mode)
1372
        switch(file->Mode)
1373
        {
1373
        {
1374
                case 'a':
1374
                case 'a':
1375
                case 'w':
1375
                case 'w':
1376
                        if(file->ByteOfCurrSector > 0)                                                                          // has data been added to the file?
1376
                        if(file->ByteOfCurrSector > 0)                                                                          // has data been added to the file?
1377
                        {
1377
                        {
1378
                                if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))// save the data still in the buffer
1378
                                if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))// save the data still in the buffer
1379
                                {
1379
                                {
1380
                                        Fat16_Deinit();
1380
                                        Fat16_Deinit();
1381
                                        return(EOF);
1381
                                        return(EOF);
1382
                                }
1382
                                }
1383
                        }
1383
                        }
1384
                        file->SectorInCache     = file->DirectorySector;
1384
                        file->SectorInCache     = file->DirectorySector;
1385
                        if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))                                       // read the directory entry for this file.
1385
                        if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))                                       // read the directory entry for this file.
1386
                        {
1386
                        {
1387
                                Fat16_Deinit();
1387
                                Fat16_Deinit();
1388
                                return(EOF);
1388
                                return(EOF);
1389
                        }
1389
                        }
1390
 
1390
 
1391
                        dir = (DirEntry_t *)file->Cache;
1391
                        dir = (DirEntry_t *)file->Cache;
1392
                        dir[file->DirectoryIndex].Size = file->Size;                                            // update file size
1392
                        dir[file->DirectoryIndex].Size = file->Size;                                            // update file size
1393
                        dir[file->DirectoryIndex].DateTime = FileDateTime(&SystemTime);         // update date time
1393
                        dir[file->DirectoryIndex].DateTime = FileDateTime(&SystemTime);         // update date time
1394
                        if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))       // write back to sd-card
1394
                        if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))       // write back to sd-card
1395
                        {
1395
                        {
1396
                                Fat16_Deinit();
1396
                                Fat16_Deinit();
1397
                                return(EOF);
1397
                                return(EOF);
1398
                        }
1398
                        }
1399
                        break;
1399
                        break;
1400
                case 'r':
1400
                case 'r':
1401
                default:
1401
                default:
1402
                        return(EOF);
1402
                        return(EOF);
1403
                        break;
1403
                        break;
1404
 
1404
 
1405
        }
1405
        }
1406
        return(0);
1406
        return(0);
1407
}
1407
}
1408
 
1408
 
1409
/****************************************************************************************************************************************/
1409
/****************************************************************************************************************************************/
1410
/*      Function:               fclose_(File *file);                                                                                                                                                                                            */
1410
/*      Function:               fclose_(File *file);                                                                                                                                                                                            */
1411
/*                                                                                                                                                                                                                                                                              */
1411
/*                                                                                                                                                                                                                                                                              */
1412
/*      Description:    This function closes the open file by writing the remaining data                                                                                                        */
1412
/*      Description:    This function closes the open file by writing the remaining data                                                                                                        */
1413
/*                                      from the buffer to the device and entering the filesize in the directory entry.                                                                         */
1413
/*                                      from the buffer to the device and entering the filesize in the directory entry.                                                                         */
1414
/*                                                                                                                                                                                                                                                                              */
1414
/*                                                                                                                                                                                                                                                                              */
1415
/*      Returnvalue:    0 on success EOF on error                                                                                                                                                                                       */
1415
/*      Returnvalue:    0 on success EOF on error                                                                                                                                                                                       */
1416
/****************************************************************************************************************************************/
1416
/****************************************************************************************************************************************/
1417
int16_t fclose_(File_t *file)
1417
int16_t fclose_(File_t *file)
1418
{
1418
{
1419
        int16_t returnvalue = EOF;
1419
        int16_t returnvalue = EOF;
1420
 
1420
 
1421
        if(file == NULL) return(returnvalue);
1421
        if(file == NULL) return(returnvalue);
1422
        returnvalue = fflush_(file);
1422
        returnvalue = fflush_(file);
1423
        UnlockFilePointer(file);
1423
        UnlockFilePointer(file);
1424
        return(returnvalue);
1424
        return(returnvalue);
1425
}
1425
}
1426
 
1426
 
1427
/********************************************************************************************************************************************/
1427
/********************************************************************************************************************************************/
1428
/*      Function:               fgetc_(File *file);                                                                                                                                                                                                             */
1428
/*      Function:               fgetc_(File *file);                                                                                                                                                                                                             */
1429
/*                                                                                                                                                                                                                                                                                      */
1429
/*                                                                                                                                                                                                                                                                                      */
1430
/*      Description:    This function reads and returns one character from the specified file. Is the end of the actual sector reached the              */
1430
/*      Description:    This function reads and returns one character from the specified file. Is the end of the actual sector reached the              */
1431
/*                                      next sector of the cluster is read. If the last sector of the cluster read the next cluster will be searched in FAT.    */
1431
/*                                      next sector of the cluster is read. If the last sector of the cluster read the next cluster will be searched in FAT.    */
1432
/*                                                                                                                                                                                                                                                                                      */
1432
/*                                                                                                                                                                                                                                                                                      */
1433
/*      Returnvalue:    The function returns the character read from the specified memorylocation as u8 casted to s16 or EOF.                                   */
1433
/*      Returnvalue:    The function returns the character read from the specified memorylocation as u8 casted to s16 or EOF.                                   */
1434
/********************************************************************************************************************************************/
1434
/********************************************************************************************************************************************/
1435
int16_t fgetc_(File_t * const file)
1435
int16_t fgetc_(File_t * const file)
1436
{
1436
{
1437
        int16_t c = EOF;
1437
        int16_t c = EOF;
1438
        uint32_t curr_sector;
1438
        uint32_t curr_sector;
1439
 
1439
 
1440
        if( (!Partition.IsValid) || (file == NULL)) return(c);
1440
        if( (!Partition.IsValid) || (file == NULL)) return(c);
1441
        // if the end of the file is not reached, get the next character.
1441
        // if the end of the file is not reached, get the next character.
1442
        if((0 < file->Size) && ((file->Position+1) < file->Size) )
1442
        if((0 < file->Size) && ((file->Position+1) < file->Size) )
1443
        {
1443
        {
1444
                curr_sector  = file->FirstSectorOfCurrCluster;          // calculate the sector of the next character to be read.
1444
                curr_sector  = file->FirstSectorOfCurrCluster;          // calculate the sector of the next character to be read.
1445
                curr_sector += file->SectorOfCurrCluster;
1445
                curr_sector += file->SectorOfCurrCluster;
1446
 
1446
 
1447
                if(file->SectorInCache != curr_sector)
1447
                if(file->SectorInCache != curr_sector)
1448
                {
1448
                {
1449
                        file->SectorInCache = curr_sector;
1449
                        file->SectorInCache = curr_sector;
1450
                        if(SD_SUCCESS != SDC_GetSector(file->SectorInCache,file->Cache))
1450
                        if(SD_SUCCESS != SDC_GetSector(file->SectorInCache,file->Cache))
1451
                        {
1451
                        {
1452
                                Fat16_Deinit();
1452
                                Fat16_Deinit();
1453
                                return(c);
1453
                                return(c);
1454
                        }
1454
                        }
1455
                }
1455
                }
1456
                c = (int16_t) file->Cache[file->ByteOfCurrSector];
1456
                c = (int16_t) file->Cache[file->ByteOfCurrSector];
1457
                file->Position++;                                                                       // increment file position
1457
                file->Position++;                                                                       // increment file position
1458
                file->ByteOfCurrSector++;                                                       // goto next byte in sector
1458
                file->ByteOfCurrSector++;                                                       // goto next byte in sector
1459
                if(file->ByteOfCurrSector >= BYTES_PER_SECTOR)          // if end of sector
1459
                if(file->ByteOfCurrSector >= BYTES_PER_SECTOR)          // if end of sector
1460
                {
1460
                {
1461
                        file->ByteOfCurrSector = 0;                                             //  reset byte location
1461
                        file->ByteOfCurrSector = 0;                                             //  reset byte location
1462
                        file->SectorOfCurrCluster++;                                    //      next sector
1462
                        file->SectorOfCurrCluster++;                                    //      next sector
1463
                        if(file->SectorOfCurrCluster >= Partition.SectorsPerCluster)    // if end of cluster is reached, the next datacluster has to be searched in the FAT.
1463
                        if(file->SectorOfCurrCluster >= Partition.SectorsPerCluster)    // if end of cluster is reached, the next datacluster has to be searched in the FAT.
1464
                        {
1464
                        {
1465
 
1465
 
1466
                                if(GetNextCluster(file))                                                                                // Sets the clusterpointer of the file to the next datacluster.
1466
                                if(GetNextCluster(file))                                                                                // Sets the clusterpointer of the file to the next datacluster.
1467
                                {
1467
                                {
1468
                                        file->SectorOfCurrCluster = 0;                                                          // start reading new cluster at first sector of the cluster.
1468
                                        file->SectorOfCurrCluster = 0;                                                          // start reading new cluster at first sector of the cluster.
1469
                                }
1469
                                }
1470
                                else // the last cluster was allready reached
1470
                                else // the last cluster was allready reached
1471
                                {
1471
                                {
1472
                                        file->SectorOfCurrCluster--;                                                    // jump back to the last sector in the last cluster
1472
                                        file->SectorOfCurrCluster--;                                                    // jump back to the last sector in the last cluster
1473
                                        file->ByteOfCurrSector = BYTES_PER_SECTOR;                              // set ByteOfCurrSector one byte over sector end
1473
                                        file->ByteOfCurrSector = BYTES_PER_SECTOR;                              // set ByteOfCurrSector one byte over sector end
1474
                                }
1474
                                }
1475
                        }
1475
                        }
1476
                }
1476
                }
1477
        }
1477
        }
1478
        return(c);
1478
        return(c);
1479
}
1479
}
1480
 
1480
 
1481
/********************************************************************************************************************************************/
1481
/********************************************************************************************************************************************/
1482
/*      Function:               fputc_( const s8 c, File *file);                                                                                                                                                                                */
1482
/*      Function:               fputc_( const s8 c, File *file);                                                                                                                                                                                */
1483
/*                                                                                                                                                                                                                                                                                      */
1483
/*                                                                                                                                                                                                                                                                                      */
1484
/*      Description:    This function writes a byte to the specified file and takes care of writing the necessary FAT- Entries.                                 */
1484
/*      Description:    This function writes a byte to the specified file and takes care of writing the necessary FAT- Entries.                                 */
1485
/*                                      next sector of the cluster is read. If the last sector of the cluster read the next cluster will be searched in FAT.    */
1485
/*                                      next sector of the cluster is read. If the last sector of the cluster read the next cluster will be searched in FAT.    */
1486
/*                                                                                                                                                                                                                                                                                      */
1486
/*                                                                                                                                                                                                                                                                                      */
1487
/*      Returnvalue:    The function returns the character written to the stream or EOF on error.                                                                                               */
1487
/*      Returnvalue:    The function returns the character written to the stream or EOF on error.                                                                                               */
1488
/********************************************************************************************************************************************/
1488
/********************************************************************************************************************************************/
1489
int16_t fputc_(const int8_t c, File_t * const file)
1489
int16_t fputc_(const int8_t c, File_t * const file)
1490
{
1490
{
1491
        uint32_t curr_sector  = 0;
1491
        uint32_t curr_sector  = 0;
1492
 
1492
 
1493
        if((!Partition.IsValid) || (file == NULL)) return(EOF);
1493
        if((!Partition.IsValid) || (file == NULL)) return(EOF);
1494
 
1494
 
1495
        // If file position equals to file size, then the end of file has reached.
1495
        // If file position equals to file size, then the end of file has reached.
1496
        // In this chase it has to be checked that the ByteOfCurrSector is BYTES_PER_SECTOR
1496
        // In this chase it has to be checked that the ByteOfCurrSector is BYTES_PER_SECTOR
1497
        // and a new cluster should be appended.
1497
        // and a new cluster should be appended.
1498
        if((file->Position >= file->Size) && (file->ByteOfCurrSector >= BYTES_PER_SECTOR))
1498
        if((file->Position >= file->Size) && (file->ByteOfCurrSector >= BYTES_PER_SECTOR))
1499
        {
1499
        {
1500
                if(!AppendCluster(file)) return(EOF);
1500
                if(!AppendCluster(file)) return(EOF);
1501
        }
1501
        }
1502
 
1502
 
1503
        curr_sector  = file->FirstSectorOfCurrCluster;
1503
        curr_sector  = file->FirstSectorOfCurrCluster;
1504
        curr_sector += file->SectorOfCurrCluster;
1504
        curr_sector += file->SectorOfCurrCluster;
1505
        if(file->SectorInCache != curr_sector)
1505
        if(file->SectorInCache != curr_sector)
1506
        {
1506
        {
1507
                file->SectorInCache = curr_sector;
1507
                file->SectorInCache = curr_sector;
1508
                if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))
1508
                if(SD_SUCCESS != SDC_GetSector(file->SectorInCache, file->Cache))
1509
                {
1509
                {
1510
                        Fat16_Deinit();
1510
                        Fat16_Deinit();
1511
                        return(EOF);
1511
                        return(EOF);
1512
                }
1512
                }
1513
        }
1513
        }
1514
 
1514
 
1515
        file->Cache[file->ByteOfCurrSector] = (uint8_t)c;                       // write databyte into the buffer. The byte will be written to the device at once
1515
        file->Cache[file->ByteOfCurrSector] = (uint8_t)c;                       // write databyte into the buffer. The byte will be written to the device at once
1516
        if(file->Size == file->Position) file->Size++;          // a character has been written to the file so the size is incremented only when the character has been added at the end of the file.
1516
        if(file->Size == file->Position) file->Size++;          // a character has been written to the file so the size is incremented only when the character has been added at the end of the file.
1517
        file->Position++;                                                                       // the actual positon within the file.
1517
        file->Position++;                                                                       // the actual positon within the file.
1518
        file->ByteOfCurrSector++;                                                       // goto next byte in sector
1518
        file->ByteOfCurrSector++;                                                       // goto next byte in sector
1519
        if(file->ByteOfCurrSector >= BYTES_PER_SECTOR)          // if the end of this sector is reached yet
1519
        if(file->ByteOfCurrSector >= BYTES_PER_SECTOR)          // if the end of this sector is reached yet
1520
        {       // save the sector to the sd-card
1520
        {       // save the sector to the sd-card
1521
                if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))
1521
                if(SD_SUCCESS != SDC_PutSector(file->SectorInCache, file->Cache))
1522
                {
1522
                {
1523
                        Fat16_Deinit();
1523
                        Fat16_Deinit();
1524
                        return(EOF);
1524
                        return(EOF);
1525
                }
1525
                }
1526
                file->ByteOfCurrSector = 0;                                             //  reset byte location
1526
                file->ByteOfCurrSector = 0;                                             //  reset byte location
1527
                file->SectorOfCurrCluster++;                                    //      next sector
1527
                file->SectorOfCurrCluster++;                                    //      next sector
1528
                if(file->SectorOfCurrCluster >= Partition.SectorsPerCluster)// if end of cluster is reached, the next datacluster has to be searched in the FAT.
1528
                if(file->SectorOfCurrCluster >= Partition.SectorsPerCluster)// if end of cluster is reached, the next datacluster has to be searched in the FAT.
1529
                {
1529
                {
1530
                        if(!GetNextCluster(file))                                                               // Sets the clusterpointer of the file to the next datacluster.
1530
                        if(!GetNextCluster(file))                                                               // Sets the clusterpointer of the file to the next datacluster.
1531
                        { // if current cluster was the last cluster of the file
1531
                        { // if current cluster was the last cluster of the file
1532
                                if(!AppendCluster(file))                                                // append a new and free cluster at the end of the file.
1532
                                if(!AppendCluster(file))                                                // append a new and free cluster at the end of the file.
1533
                                {
1533
                                {
1534
                                        file->SectorOfCurrCluster--;                            // jump back to last sector of last cluster
1534
                                        file->SectorOfCurrCluster--;                            // jump back to last sector of last cluster
1535
                                        file->ByteOfCurrSector = BYTES_PER_SECTOR;      // set byte location to 1 byte over sector len
1535
                                        file->ByteOfCurrSector = BYTES_PER_SECTOR;      // set byte location to 1 byte over sector len
1536
                                        return(EOF);
1536
                                        return(EOF);
1537
                                }
1537
                                }
1538
                        }
1538
                        }
1539
                        else // next cluster
1539
                        else // next cluster
1540
                        {
1540
                        {
1541
                                file->SectorOfCurrCluster = 0;                                                  // start reading new cluster at first sector of the cluster.
1541
                                file->SectorOfCurrCluster = 0;                                                  // start reading new cluster at first sector of the cluster.
1542
                        }
1542
                        }
1543
                }
1543
                }
1544
        }
1544
        }
1545
        return(0);
1545
        return(0);
1546
}
1546
}
1547
 
1547
 
1548
 
1548
 
1549
/****************************************************************************************************************************************/
1549
/****************************************************************************************************************************************/
1550
/*      Function:               fread_(void *buffer, uint32_t size, uint32_t count, File *File);                                                                                                                                */
1550
/*      Function:               fread_(void *buffer, uint32_t size, uint32_t count, File *File);                                                                                                                                */
1551
/*                                                                                                                                                                                                                                                                              */
1551
/*                                                                                                                                                                                                                                                                              */
1552
/*      Description:    This function reads count objects of the specified size                                                                                                                         */
1552
/*      Description:    This function reads count objects of the specified size                                                                                                                         */
1553
/*                                      from the actual position of the file to the specified buffer.                                                                                                           */
1553
/*                                      from the actual position of the file to the specified buffer.                                                                                                           */
1554
/*                                                                                                                                                                                                                                                                              */
1554
/*                                                                                                                                                                                                                                                                              */
1555
/*      Returnvalue:    The function returns the number of objects (not bytes) read from the file.                                                                                      */
1555
/*      Returnvalue:    The function returns the number of objects (not bytes) read from the file.                                                                                      */
1556
/****************************************************************************************************************************************/
1556
/****************************************************************************************************************************************/
1557
uint32_t fread_(void * const buffer, uint32_t size, uint32_t count, File_t * const file)
1557
uint32_t fread_(void * const buffer, uint32_t size, uint32_t count, File_t * const file)
1558
{
1558
{
1559
        uint32_t object_cnt     = 0;                                                                                    // count the number of objects read from the file.
1559
        uint32_t object_cnt     = 0;                                                                                    // count the number of objects read from the file.
1560
        uint32_t object_size = 0;                                                                                       // count the number of bytes read from the actual object.
1560
        uint32_t object_size = 0;                                                                                       // count the number of bytes read from the actual object.
1561
        uint8_t *pbuff          = 0;                                                                                    // a pointer to the actual bufferposition.
1561
        uint8_t *pbuff          = 0;                                                                                    // a pointer to the actual bufferposition.
1562
        uint8_t success      = 1;                                                                                       // no error occured during read operation to the file.
1562
        uint8_t success      = 1;                                                                                       // no error occured during read operation to the file.
1563
        int16_t c;
1563
        int16_t c;
1564
 
1564
 
1565
        if((!Partition.IsValid) || (file == NULL) || (buffer == NULL)) return(0);
1565
        if((!Partition.IsValid) || (file == NULL) || (buffer == NULL)) return(0);
1566
 
1566
 
1567
        pbuff = (uint8_t *) buffer;                                                                                     // cast the void pointer to an u8 *
1567
        pbuff = (uint8_t *) buffer;                                                                                     // cast the void pointer to an u8 *
1568
 
1568
 
1569
        while((object_cnt < count) && success)
1569
        while((object_cnt < count) && success)
1570
        {
1570
        {
1571
                object_size = size;
1571
                object_size = size;
1572
                while((size > 0) && success)
1572
                while((size > 0) && success)
1573
                {
1573
                {
1574
                        c = fgetc_(file);
1574
                        c = fgetc_(file);
1575
                        if(c != EOF)
1575
                        if(c != EOF)
1576
                        {
1576
                        {
1577
                                *pbuff = (uint8_t)c;                                                                    // read a byte from the buffer to the opened file.
1577
                                *pbuff = (uint8_t)c;                                                                    // read a byte from the buffer to the opened file.
1578
                                pbuff++;
1578
                                pbuff++;
1579
                                size--;
1579
                                size--;
1580
                        }
1580
                        }
1581
                        else // error or end of file reached
1581
                        else // error or end of file reached
1582
                        {
1582
                        {
1583
                                success = 0;
1583
                                success = 0;
1584
                        }
1584
                        }
1585
                }
1585
                }
1586
                if(success) object_cnt++;
1586
                if(success) object_cnt++;
1587
        }
1587
        }
1588
        return(object_cnt);                                                                                             // return the number of objects succesfully read from the file
1588
        return(object_cnt);                                                                                             // return the number of objects succesfully read from the file
1589
}
1589
}
1590
 
1590
 
1591
 
1591
 
1592
/****************************************************************************************************************************************/
1592
/****************************************************************************************************************************************/
1593
/*      Function:               fwrite_(void *buffer, uint32_t size, uint32_t count, File *file);                                                                                                                               */
1593
/*      Function:               fwrite_(void *buffer, uint32_t size, uint32_t count, File *file);                                                                                                                               */
1594
/*                                                                                                                                                                                                                                                                              */
1594
/*                                                                                                                                                                                                                                                                              */
1595
/*      Description:    This function writes count objects of the specified size                                                                                                                        */
1595
/*      Description:    This function writes count objects of the specified size                                                                                                                        */
1596
/*                                      from the buffer pointer to the actual position in the file.                                                                                                                     */
1596
/*                                      from the buffer pointer to the actual position in the file.                                                                                                                     */
1597
/*                                                                                                                                                                                                                                                                              */
1597
/*                                                                                                                                                                                                                                                                              */
1598
/*      Returnvalue:    The function returns the number of objects (not bytes) read from the file.                                                                                      */
1598
/*      Returnvalue:    The function returns the number of objects (not bytes) read from the file.                                                                                      */
1599
/****************************************************************************************************************************************/
1599
/****************************************************************************************************************************************/
1600
uint32_t fwrite_(void * const buffer, uint32_t size, uint32_t count, File_t * const file)
1600
uint32_t fwrite_(void * const buffer, uint32_t size, uint32_t count, File_t * const file)
1601
{
1601
{
1602
        uint32_t object_cnt     = 0;                                                                                                            // count the number of objects written to the file.
1602
        uint32_t object_cnt     = 0;                                                                                                            // count the number of objects written to the file.
1603
        uint32_t object_size = 0;                                                                                                               // count the number of bytes written from the actual object.
1603
        uint32_t object_size = 0;                                                                                                               // count the number of bytes written from the actual object.
1604
        uint8_t *pbuff      = 0;                                                                                                                // a pointer to the actual bufferposition.
1604
        uint8_t *pbuff      = 0;                                                                                                                // a pointer to the actual bufferposition.
1605
        uint8_t success      = 1;                                                                                                               // no error occured during write operation to the file.
1605
        uint8_t success      = 1;                                                                                                               // no error occured during write operation to the file.
1606
        int16_t c;
1606
        int16_t c;
1607
 
1607
 
1608
        if((!Partition.IsValid) || (file == NULL) || (buffer == NULL)) return(0);
1608
        if((!Partition.IsValid) || (file == NULL) || (buffer == NULL)) return(0);
1609
 
1609
 
1610
        pbuff = (uint8_t *) buffer;                                                                                                             // cast the void pointer to an u8 *
1610
        pbuff = (uint8_t *) buffer;                                                                                                             // cast the void pointer to an u8 *
1611
 
1611
 
1612
        while((object_cnt < count) && success)
1612
        while((object_cnt < count) && success)
1613
        {
1613
        {
1614
                object_size = size;
1614
                object_size = size;
1615
                while((size > 0) && success)
1615
                while((size > 0) && success)
1616
                {
1616
                {
1617
                        c = fputc_(*pbuff, file);                                                                               // write a byte from the buffer to the opened file.
1617
                        c = fputc_(*pbuff, file);                                                                               // write a byte from the buffer to the opened file.
1618
                        if(c != EOF)
1618
                        if(c != EOF)
1619
                        {
1619
                        {
1620
                                pbuff++;
1620
                                pbuff++;
1621
                                size--;
1621
                                size--;
1622
                        }
1622
                        }
1623
                        else
1623
                        else
1624
                        {
1624
                        {
1625
                                success = 0;
1625
                                success = 0;
1626
                        }
1626
                        }
1627
                }
1627
                }
1628
                if(success) object_cnt++;
1628
                if(success) object_cnt++;
1629
        }
1629
        }
1630
 
1630
 
1631
        return(object_cnt);                                                                                                                             // return the number of objects succesfully written to the file
1631
        return(object_cnt);                                                                                                                             // return the number of objects succesfully written to the file
1632
}
1632
}
1633
 
1633
 
1634
 
1634
 
1635
/****************************************************************************************************************************************/
1635
/****************************************************************************************************************************************/
1636
/*      Function:               fputs_(const int8_t *string, File_t *File);                                                                                                                                                             */
1636
/*      Function:               fputs_(const int8_t *string, File_t *File);                                                                                                                                                             */
1637
/*                                                                                                                                                                                                                                                                              */
1637
/*                                                                                                                                                                                                                                                                              */
1638
/*      Description:    This function writes a string to the specified file.                                                                                                                            */
1638
/*      Description:    This function writes a string to the specified file.                                                                                                                            */
1639
/*                                                                                                                                                                                                                                                                              */
1639
/*                                                                                                                                                                                                                                                                              */
1640
/*      Returnvalue:    The function returns a no negative value or EOF on error.                                                                                                                       */
1640
/*      Returnvalue:    The function returns a no negative value or EOF on error.                                                                                                                       */
1641
/****************************************************************************************************************************************/
1641
/****************************************************************************************************************************************/
1642
int16_t fputs_(int8_t * const string, File_t * const file)
1642
int16_t fputs_(int8_t * const string, File_t * const file)
1643
{
1643
{
1644
        uint8_t i=0;
1644
        uint8_t i=0;
1645
        int16_t c = 0;
1645
        int16_t c = 0;
1646
 
1646
 
1647
        if((!Partition.IsValid) || (file == NULL) || (string == NULL)) return(0);
1647
        if((!Partition.IsValid) || (file == NULL) || (string == NULL)) return(0);
1648
 
1648
 
1649
        while((string[i] != 0)&& (c != EOF))
1649
        while((string[i] != 0)&& (c != EOF))
1650
        {
1650
        {
1651
                c = fputc_(string[i], file);
1651
                c = fputc_(string[i], file);
1652
                i++;
1652
                i++;
1653
        }
1653
        }
1654
        return(c);
1654
        return(c);
1655
}
1655
}
1656
 
1656
 
1657
/****************************************************************************************************************************************/
1657
/****************************************************************************************************************************************/
1658
/*      Function:               fgets_(int8 *, int16_t , File_t *);                                                                                                                                                                             */
1658
/*      Function:               fgets_(int8 *, int16_t , File_t *);                                                                                                                                                                             */
1659
/*                                                                                                                                                                                                                                                                              */
1659
/*                                                                                                                                                                                                                                                                              */
1660
/*      Description:    This function reads a string from the file to the specifies string.                                                                                             */
1660
/*      Description:    This function reads a string from the file to the specifies string.                                                                                             */
1661
/*                                                                                                                                                                                                                                                                              */
1661
/*                                                                                                                                                                                                                                                                              */
1662
/*      Returnvalue:    A pointer to the string read from the file or 0 on error.                                                                                                                       */
1662
/*      Returnvalue:    A pointer to the string read from the file or 0 on error.                                                                                                                       */
1663
/****************************************************************************************************************************************/
1663
/****************************************************************************************************************************************/
1664
int8_t * fgets_(int8_t * const string, int16_t length, File_t * const file)
1664
int8_t * fgets_(int8_t * const string, int16_t length, File_t * const file)
1665
{
1665
{
1666
        int8_t *pbuff;
1666
        int8_t *pbuff;
1667
        int16_t c = 0, bytecount;
1667
        int16_t c = 0, bytecount;
1668
 
1668
 
1669
        if((!Partition.IsValid) || (file == NULL) || (string == NULL) || (length > 1)) return (0);
1669
        if((!Partition.IsValid) || (file == NULL) || (string == NULL) || (length > 1)) return (0);
1670
        pbuff = string;
1670
        pbuff = string;
1671
        bytecount = length;
1671
        bytecount = length;
1672
        while(bytecount > 1)                                                    // read the count-1 characters from the file to the string.
1672
        while(bytecount > 1)                                                    // read the count-1 characters from the file to the string.
1673
        {
1673
        {
1674
                c = fgetc_(file);                                                       // read a character from the opened file.
1674
                c = fgetc_(file);                                                       // read a character from the opened file.
1675
                switch(c)
1675
                switch(c)
1676
                {
1676
                {
1677
                        case 0x0A:
1677
                        case 0x0A:
1678
                                *pbuff = 0;                                                     // set string terminator
1678
                                *pbuff = 0;                                                     // set string terminator
1679
                                return(string);                                         // stop loop
1679
                                return(string);                                         // stop loop
1680
                                break;
1680
                                break;
1681
 
1681
 
1682
                        case EOF:
1682
                        case EOF:
1683
                                *pbuff = 0;                                                     // set string terminator
1683
                                *pbuff = 0;                                                     // set string terminator
1684
                                return(0);
1684
                                return(0);
1685
                        default:
1685
                        default:
1686
                                *pbuff++ = (int8_t)c;                           // copy byte to string
1686
                                *pbuff++ = (int8_t)c;                           // copy byte to string
1687
                                bytecount--;
1687
                                bytecount--;
1688
                                break;
1688
                                break;
1689
                }
1689
                }
1690
        }
1690
        }
1691
        *pbuff = 0;
1691
        *pbuff = 0;
1692
        return(string);
1692
        return(string);
1693
}
1693
}
1694
 
1694
 
1695
/****************************************************************************************************************************************/
1695
/****************************************************************************************************************************************/
1696
/*      Function:               fexist_(const int8_t*);                                                                                                                                                                                                 */
1696
/*      Function:               fexist_(const int8_t*);                                                                                                                                                                                                 */
1697
/*                                                                                                                                                                                                                                                                              */
1697
/*                                                                                                                                                                                                                                                                              */
1698
/*      Description:    This function checks if a file already exist.                                                                                                                                           */
1698
/*      Description:    This function checks if a file already exist.                                                                                                                                           */
1699
/*                                                                                                                                                                                                                                                                              */
1699
/*                                                                                                                                                                                                                                                                              */
1700
/*      Returnvalue:    1 if the file exist else 0.                                                                                                                                                                                     */
1700
/*      Returnvalue:    1 if the file exist else 0.                                                                                                                                                                                     */
1701
/****************************************************************************************************************************************/
1701
/****************************************************************************************************************************************/
1702
uint8_t fexist_(const int8_t* filename)
1702
uint8_t fexist_(int8_t* const filename)
1703
{
1703
{
1704
        uint8_t exist = 0;
1704
        uint8_t exist = 0;
1705
        File_t *file = 0;
1705
        File_t *file = 0;
1706
        file = LockFilePointer();
1706
        file = LockFilePointer();
1707
        exist = FileExist(filename, ATTR_NONE, ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL, file);
1707
        exist = FileExist(filename, ATTR_NONE, ATTR_SUBDIRECTORY|ATTR_VOLUMELABEL, file);
1708
        UnlockFilePointer(file);
1708
        UnlockFilePointer(file);
1709
        return(exist);
1709
        return(exist);
1710
}
1710
}
1711
 
1711
 
1712
/****************************************************************************************************************************************/
1712
/****************************************************************************************************************************************/
1713
/*      Function:               feof_(File_t *File);                                                                                                                                                                                            */
1713
/*      Function:               feof_(File_t *File);                                                                                                                                                                                            */
1714
/*                                                                                                                                                                                                                                                                              */
1714
/*                                                                                                                                                                                                                                                                              */
1715
/*      Description:    This function checks wether the end of the file has been reached.                                                                                                                                               */
1715
/*      Description:    This function checks wether the end of the file has been reached.                                                                                                                                               */
1716
/*                                                                                                                                                                                                                                                                              */
1716
/*                                                                                                                                                                                                                                                                              */
1717
/*      Returnvalue:    0 if the end of the file was not reached otherwise 1.                                                                                                                                                                           */
1717
/*      Returnvalue:    0 if the end of the file was not reached otherwise 1.                                                                                                                                                                           */
1718
/****************************************************************************************************************************************/
1718
/****************************************************************************************************************************************/
1719
uint8_t feof_(File_t *file)
1719
uint8_t feof_(File_t *file)
1720
{
1720
{
1721
        if(((file->Position)+1) < (file->Size))
1721
        if(((file->Position)+1) < (file->Size))
1722
        {
1722
        {
1723
                return(0);
1723
                return(0);
1724
        }
1724
        }
1725
        else
1725
        else
1726
        {
1726
        {
1727
                return(1);
1727
                return(1);
1728
        }
1728
        }
1729
}
1729
}
1730
 
1730
 
1731
 
1731
 
1732
 
1732