/trunk/Navi-Ctrl.Uv2 |
---|
23,8 → 23,8 |
File 1,1,<.\GPSUart.c><GPSUart.c> |
File 1,1,<.\usb.c><usb.c> |
File 1,1,<.\fat16.c><fat16.c> |
File 1,1,<.\settings.c><settings.c> |
File 1,1,<.\sdc.c><sdc.c> |
File 1,1,<.\settings.c><settings.c> |
File 1,1,<.\ssc.c><ssc.c> |
File 1,1,<.\usb_desc.c><usb_desc.c> |
File 1,1,<.\usb_endp.c><usb_endp.c> |
31,6 → 31,10 |
File 1,1,<.\usb_istr.c><usb_istr.c> |
File 1,1,<.\usb_prop.c><usb_prop.c> |
File 1,1,<.\usb_pwr.c><usb_pwr.c> |
File 1,1,<.\crc16.c><crc16.c> |
File 1,1,<.\kml.c><kml.c> |
File 2,5,<.\kml.h><kml.h> |
File 2,5,<.\crc16.h><crc16.h> |
File 2,5,<.\ramfunc.h><ramfunc.h> |
File 2,5,<.\main.h><main.h> |
File 2,5,<.\uart.h><uart.h> |
47,6 → 51,7 |
File 2,5,<.\GPS.h><GPS.h> |
File 2,5,<.\GPSUart.h><GPSUart.h> |
File 2,5,<.\settings.h><settings.h> |
File 2,5,<.\kml_header.h><kml_header.h> |
File 3,2,<.\startup912.s><startup912.s> |
File 4,1,<.\libstr91x\src\91x_scu.c><91x_scu.c> |
File 4,1,<.\libstr91x\src\91x_gpio.c><91x_gpio.c> |
56,6 → 61,7 |
File 4,1,<.\libstr91x\src\91x_ssp.c><91x_ssp.c> |
File 4,1,<.\libstr91x\src\91x_i2c.c><91x_i2c.c> |
File 4,1,<.\libstr91x\src\91x_fmi.c><91x_fmi.c> |
File 4,1,<.\libstr91x\src\91x_wiu.c><91x_wiu.c> |
File 6,1,<.\usblibrary\src\usb_regs.c><usb_regs.c> |
File 6,1,<.\usblibrary\src\usb_core.c><usb_core.c> |
File 6,1,<.\usblibrary\src\usb_init.c><usb_init.c> |
155,3 → 161,25 |
FLASH4 () |
EndOpt |
Options 1,1,0 // Group 'Source Code' |
PropFld { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } |
IncBld=2 |
AlwaysBuild=2 |
GenAsm=2 |
AsmAsm=2 |
PublicsOnly=2 |
StopCode=11 |
CustArgs () |
LibMods () |
ACCFLG { 170,2,16,32,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } |
ACMISC () |
ACDEFN () |
ACUDEF () |
ACINCD () |
AASFLG { 10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } |
AAMISC () |
AADEFN () |
AAUDEF () |
AAINCD () |
EndOpt |
/trunk/crc16.c |
---|
0,0 → 1,47 |
#include "91x_lib.h" |
static const u16 crc16tab[256]= |
{ |
0x0000,0x1021,0x2042,0x3063,0x4084,0x50a5,0x60c6,0x70e7, |
0x8108,0x9129,0xa14a,0xb16b,0xc18c,0xd1ad,0xe1ce,0xf1ef, |
0x1231,0x0210,0x3273,0x2252,0x52b5,0x4294,0x72f7,0x62d6, |
0x9339,0x8318,0xb37b,0xa35a,0xd3bd,0xc39c,0xf3ff,0xe3de, |
0x2462,0x3443,0x0420,0x1401,0x64e6,0x74c7,0x44a4,0x5485, |
0xa56a,0xb54b,0x8528,0x9509,0xe5ee,0xf5cf,0xc5ac,0xd58d, |
0x3653,0x2672,0x1611,0x0630,0x76d7,0x66f6,0x5695,0x46b4, |
0xb75b,0xa77a,0x9719,0x8738,0xf7df,0xe7fe,0xd79d,0xc7bc, |
0x48c4,0x58e5,0x6886,0x78a7,0x0840,0x1861,0x2802,0x3823, |
0xc9cc,0xd9ed,0xe98e,0xf9af,0x8948,0x9969,0xa90a,0xb92b, |
0x5af5,0x4ad4,0x7ab7,0x6a96,0x1a71,0x0a50,0x3a33,0x2a12, |
0xdbfd,0xcbdc,0xfbbf,0xeb9e,0x9b79,0x8b58,0xbb3b,0xab1a, |
0x6ca6,0x7c87,0x4ce4,0x5cc5,0x2c22,0x3c03,0x0c60,0x1c41, |
0xedae,0xfd8f,0xcdec,0xddcd,0xad2a,0xbd0b,0x8d68,0x9d49, |
0x7e97,0x6eb6,0x5ed5,0x4ef4,0x3e13,0x2e32,0x1e51,0x0e70, |
0xff9f,0xefbe,0xdfdd,0xcffc,0xbf1b,0xaf3a,0x9f59,0x8f78, |
0x9188,0x81a9,0xb1ca,0xa1eb,0xd10c,0xc12d,0xf14e,0xe16f, |
0x1080,0x00a1,0x30c2,0x20e3,0x5004,0x4025,0x7046,0x6067, |
0x83b9,0x9398,0xa3fb,0xb3da,0xc33d,0xd31c,0xe37f,0xf35e, |
0x02b1,0x1290,0x22f3,0x32d2,0x4235,0x5214,0x6277,0x7256, |
0xb5ea,0xa5cb,0x95a8,0x8589,0xf56e,0xe54f,0xd52c,0xc50d, |
0x34e2,0x24c3,0x14a0,0x0481,0x7466,0x6447,0x5424,0x4405, |
0xa7db,0xb7fa,0x8799,0x97b8,0xe75f,0xf77e,0xc71d,0xd73c, |
0x26d3,0x36f2,0x0691,0x16b0,0x6657,0x7676,0x4615,0x5634, |
0xd94c,0xc96d,0xf90e,0xe92f,0x99c8,0x89e9,0xb98a,0xa9ab, |
0x5844,0x4865,0x7806,0x6827,0x18c0,0x08e1,0x3882,0x28a3, |
0xcb7d,0xdb5c,0xeb3f,0xfb1e,0x8bf9,0x9bd8,0xabbb,0xbb9a, |
0x4a75,0x5a54,0x6a37,0x7a16,0x0af1,0x1ad0,0x2ab3,0x3a92, |
0xfd2e,0xed0f,0xdd6c,0xcd4d,0xbdaa,0xad8b,0x9de8,0x8dc9, |
0x7c26,0x6c07,0x5c64,0x4c45,0x3ca2,0x2c83,0x1ce0,0x0cc1, |
0xef1f,0xff3e,0xcf5d,0xdf7c,0xaf9b,0xbfba,0x8fd9,0x9ff8, |
0x6e17,0x7e36,0x4e55,0x5e74,0x2e93,0x3eb2,0x0ed1,0x1ef0 |
}; |
u16 CRC16(const u8 *pBuffer, u32 len) |
{ |
register u32 counter; |
register u16 crc = 0; |
for( counter = 0; counter < len; counter++) |
crc = (crc<<8) ^ crc16tab[((crc>>8) ^ *pBuffer++)&0x00FF]; |
return crc; |
} |
/trunk/crc16.h |
---|
0,0 → 1,6 |
#ifndef _CRC16_H |
#define _CRC16_H |
extern u16 CRC16(const u8 * pBuffer, u32 len); |
#endif // _CRC16_H |
/trunk/fat16.c |
---|
60,23 → 60,30 |
//________________________________________________________________________________________________________________________________________ |
// Module name: fat16.c |
// Compiler used: avr-gcc 3.4.5 |
// Last Modifikation: 24.07.2007 |
// Version: 1.24 |
// Last Modifikation: 21.04.2008 |
// Version: 1.28 |
// Authors: Stephan Busker |
// Description: Source files for FAT16 implementation with read and write-access using AVR-Mikrocontrollers |
// Copyright (C) 2007 Stephan Busker |
//........................................................................................................................................ |
// Functions: extern u8 InitFat16(void); |
// u8 fopen_(u8 *fname,s8 mode, File *file); |
// void fclose_(File *file); |
// u32 fread_(void *buffer, u32 size, u32 count, File *file); |
// u32 fwrite_(void *buffer, u32 size, u32 count, File *file); |
// s16 fseek_(File *file, s32 offset, s16 origin); |
// s8 fgets8_(File *file); |
// u8 fopen_(s8 *fname,s8 mode, File *file); |
// void fclose_(File *file); |
// u32 fread_(void *buffer, u32 size, u32 count, File *file); |
// u32 fwrite_(void *buffer, u32 size, u32 count, File *file); |
// s16 fseek_(File *file, s32 offset, s16 origin); |
// s8 fgets_(s8 *string, s16 count, File *file); |
// u8 fputchar_(File *file,s8 c); |
// u8 fputs_(File *file,s8 *string); |
// s8 * fgets(s8 *, s16, File); |
// u8 fexist_(u8*, File *file); |
// s8 * fgets(s8 *, s16, File); |
// u8 fexist_(u8*); |
// u8 mkdir__(s8 *name); |
// u8 chdir__(s8 *name); |
// u8 findfirst_(s8 *fname, Find *item, u8 attribute); |
// u8 findnext_(Find *item); |
// u8 fdelete_(s8 *fname) |
// u8 rmdir_(s8 *dname) |
// u16 feof_(File); |
//........................................................................................................................................ |
// ext. functions: extern u8 SDC_GetSector (u32,u8 *); |
// extern u8 SDC_PutSector (u32,u8 *); |
88,7 → 95,6 |
//________________________________________________________________________________________________________________________________________ |
// |
// Global variables needed for read- or write-acces to the FAT16- filesystem. |
95,25 → 101,24 |
// |
//________________________________________________________________________________________________________________________________________ |
u8 SectorsPerCluster = 0; // how many sectors does a cluster contain? |
u8 FatCopies = 0; // Numbers of copies of the FAT |
u16 PossibleRootEntries = 0; // Possible number of entries in the root directory. |
u16 SectorsPerFat = 0; // how many sectors does a fat16 contain? |
u32 ReservedSectors = 0; // Sectors reserved by the filesystem. |
u32 FirstPartitionSector = 0; // Distance in sectors between the first partition and the master bootrecord. |
u32 FileAllocationTable = 0; // pointer to the first FAT |
u32 RootDirectory = 0; // Pointer to the rootdirectory of the first partition. |
u32 FirstDataCluster = 0; // Pointer to the first cluster containing data (cluster0). |
//u8 FileBuffer[512]; // Buffer for read and write operation from or to the mmc. |
u8 SectorsPerCluster = 0; // how many sectors does a cluster contain? |
u8 FatCopies = 0; // Numbers of copies of the FAT |
u16 PossibleRootEntries = 0; // Possible number of entries in the root directory. |
u16 SectorsPerFat = 0; // how many sectors does a fat16 contain? |
u32 ReservedSectors = 0; // Sectors reserved by the filesystem. |
u32 FirstPartitionSector = 0; // Distance in sectors between the first partition and the master bootrecord. |
u32 FileAllocationTable = 0; // pointer to the first FAT |
u32 RootDirectory = 0; // Pointer to the rootdirectory of the first partition. |
u32 FirstDataCluster = 0; // Pointer to the first cluster containing data (cluster0). |
u32 CWD = 0; // Pointer startcluster to the current working directory |
struct DirEntry *DirectoryEntry; // Pointer to an entry of the directory. |
struct FatEntry *Fat; // Pointer to an entry of the fat (next clusterposition). |
File FilePointer[__MAX_FILES_USED]; // Allocate Memmoryspace for each filepointer used. |
struct DirEntry *DirectoryEntry; // Pointer to an entry of the directory. |
struct FatEntry *Fat; // Pointer to an entry of the fat (next clusterposition). |
File FilePointer[__MAX_FILES_USED]; // Allocate Memmoryspace for each filepointer used. |
//________________________________________________________________________________________________________________________________________ |
// Funtion: InitFat16(void); |
// |
120,7 → 125,7 |
// Description: This function reads the Masterbootrecord and finds the position of the Volumebootrecord, the FAT and the Rootdirectory |
// and stores the information in global variables. |
// |
// Returnvalue: The function returns "0" if the filesystem could not be initialized because no partition was found on the disc. |
// Returnvalue: The function returns "0" if the filesystem could not be initialized because no partition was found on the volume. |
//________________________________________________________________________________________________________________________________________ |
u8 InitFat16(void) |
127,122 → 132,109 |
{ |
u8 retvalue = 0; |
u8 cnt = 0; |
struct VBR_Entry *VBR; // Pointer to the VolumeBootRecord. |
struct MBR_Entry *MBR; // Pointer to the masterbootrecord. |
struct VBR_Entry *VBR; // Pointer to the VolumeBootRecord. |
struct MBR_Entry *MBR; // Pointer to the masterbootrecord. |
File *file; |
for(cnt=0;cnt<__MAX_FILES_USED;cnt++) |
{ |
FilePointer[cnt].state = _UNUSED; // declare the filepointers as unused. |
FilePointer[cnt].state = _UNUSED; // declare the filepointers as unused. |
} |
file = &FilePointer[0]; |
while((SDC_Init() != 0) && (cnt++<200)); // initialise the sdcard. |
if(cnt <200) //sdcard initialised succesfully |
SerialPutString("\n\rFAT16 init..."); |
while((SDC_Init() != SD_SUCCESS) && (cnt++<100)); |
if(cnt <100) // sdcard initialised succesfully |
{ |
SDC_GetSector((u32)MBR_SECTOR,file->buffer); // Read the MasterBootRecord from mmc. |
SDC_GetSector((u32)_MBR_SECTOR,file->buffer); // Read the MasterBootRecord from mmc. |
MBR = (struct MBR_Entry *) file->buffer; |
FirstPartitionSector = MBR->PartitionEntry1.NoSectorsBeforePartition; |
SDC_GetSector(FirstPartitionSector,file->buffer); // Read the volume bootrecord from mmc. |
if((MBR->PartitionEntry1.Type == _FAT16_32_MB_BIOS_Extension) || |
(MBR->PartitionEntry1.Type == _FAT16_ST_32_MB) || |
(MBR->PartitionEntry1.Type == _FAT16_LT_32_MB)) |
{ |
SDC_GetSector(FirstPartitionSector,file->buffer); // Read the volume bootrecord from mmc. |
VBR = (struct VBR_Entry *) file->buffer; // Enter the VBR using the structure VBR_Entry. |
SectorsPerCluster = VBR->SectorsPerCluster; // Number of sectors per cluster. Depends on the memorysize of the sd-card. |
FatCopies = VBR->NoFATCopies; // Number of fatcopies. |
PossibleRootEntries = VBR->MaxRootEntries; // How many Entries are possible in the rootdirectory (FAT16 allows max. 512 entries). |
SectorsPerFat = VBR->SectorsPerFAT; // The number of sectors per FAT. |
ReservedSectors = VBR->ReservedSectors; // calculate the sectorpositon of the FAT, the Rootdirectory and the first Datacluster. |
VBR = (struct VBR_Entry *) file->buffer; // Enter the VBR using the structure VBR_Entry. |
SectorsPerCluster = VBR->SectorsPerCluster; // Number of sectors per cluster. Depends on the memorysize of the sd-card. |
FatCopies = VBR->NoFATCopies; // Number of fatcopies. |
PossibleRootEntries = VBR->MaxRootEntries; // How many Entries are possible in the rootdirectory (FAT16 allows max. 512 entries). |
SectorsPerFat = VBR->SectorsPerFAT; // The number of sectors per FAT. |
ReservedSectors = VBR->ReservedSectors; // calculate the sectorpositon of the FAT, the Rootdirectory and the first Datacluster. |
FileAllocationTable = (u32)(FirstPartitionSector + (u32)ReservedSectors); // Calculate the position of the FileAllocationTable. |
RootDirectory = (u32)((u32)FileAllocationTable + (u32)((u32)SectorsPerFat*(u32)FatCopies)); // Calculate the position of the Rootdirectory. |
FirstDataCluster = (u32)((u32)RootDirectory + ((u32)(PossibleRootEntries>>4))); // Calculate the position of the first datacluster. |
if((file->buffer[0x36]=='F') &&(file->buffer[0x37]=='A')&&(file->buffer[0x38]=='T')&&(file->buffer[0x39]=='1')&&(file->buffer[0x3A]=='6')) |
{ |
FileAllocationTable = (u32)(FirstPartitionSector + (u32)ReservedSectors); // Calculate the position of the FileAllocationTable. |
RootDirectory = (u32)((u32)FileAllocationTable + (u32)((u32)SectorsPerFat*(u32)FatCopies)); // Calculate the position of the Rootdirectory. |
FirstDataCluster = (u32)((u32)RootDirectory + ((u32)(PossibleRootEntries>>4))); // Calculate the position of the first datacluster. |
CWD = RootDirectory; // The actual directory is the rootdirectory. |
retvalue = 1; |
SerialPutString("\n\rfilesystem ok"); |
str_Volume.state = INITIALIZED; |
} |
else |
{ |
str_Volume.state = NOT_INITIALIZED; |
SerialPutString("\n\rfilesystem nok"); |
} |
} |
return(retvalue); |
} |
//________________________________________________________________________________________________________________________________________ |
// Funtion: File * fopen_(u8*, u8 *, File *file); |
// Funtion: File * fopen_(u8*, u8 *); |
// |
// Description: This function looks for the specified file in the rootdirectory of the drive. If the file is found the number of the |
// corrosponding datacluster is returned to main. Only modes 'r' (reading) and 'a' append are implemented yet. |
// Description: This function looks for the file to be opened in the directory specified by the variable "CWD" of the drive. |
// If the file was found this function returns a filepoiner to the opened file otherwise NULL// |
// |
// Return: 0 = faild to open speicified file |
// 1 = file opened |
// Return: Pointer to the opened file or NULL |
// |
//________________________________________________________________________________________________________________________________________ |
File * fopen_(u8 *fname, s8 mode) |
File * fopen_(s8 *fname, s8 mode) |
{ |
u32 cluster_temp = 0; |
u8 name[11] = " "; |
u16 temp = 0; |
File *file; |
file=0; |
for(temp = 0;temp<__MAX_FILES_USED;temp++) |
file = ReserveFilePointer(); // reserve a filepointer. |
if(file != NULL) // A free filepointer was found. |
{ |
if(FilePointer[temp].state == _UNUSED) // free filepointer found? |
{ |
file = &FilePointer[temp]; |
FilePointer[temp].state = _USED; // mark as used. |
break; |
} |
} |
if(file == 0) return(file); // no valid pointer |
file->mode = mode; // mode of fileoperation (read,write) |
file->start_cluster = 0; // Sectorpointer to the first sector of the first datacluster of the file. |
file->cluster_pointer = 0; // Pointer to the cluster which is edited at the moment. |
file->sector_index = 0; // The sector which is edited at the moment (cluster_pointer + sector_index). |
file->byte_index = 0; // The bytelocation within the current sector (cluster_pointer + sector_index + byte_index). |
file->mode = mode; // mode of fileoperation (read,write) |
file->filesize = 0; // the size of the opend file in bytes. |
file->fileposition = 0; // pointer to a character within the file 0 < fileposition < filesize |
file->sector_in_buffer = 0; // the last sector read, wich is still in the sectorbuffer. |
file->directory_sector = 0; // the sectorposition where the directoryentry has been made. |
file->directory_index = 0; // the index to the directoryentry within the specified sector. |
file->attribute = 0; // the attribute of the file opened. |
if(ScanSubDirectories(&fname[0], file)) // Is the specified filepath available? |
{ |
SeperateFileName(&fname[0], &name[0]); // seperate the filename and attribute from the filepath and bring them in the correct format. |
file->attribute = _FILE; |
if(SeekDirectoryEntry(&name[0], file)) // if file was found |
if(SeekFileInDirectory(fname, file)) // if file was found |
{ |
SerialPutString("ok"); |
if(mode == 'a') // open existing file for writing (append data at the end of the file) |
{ |
fseek_(file, 0, SEEK_END); // fseek points to the end of the file |
} |
return(file); |
} |
} |
else |
{ |
if((mode == 'a') || (mode == 'w')) // specified file doesn't exist so create new file for writing data. |
{ |
cluster_temp = (u32)FindNextFreeCluster(file); // the next free cluster on the disk. |
if(cluster_temp) // if a free cluster is available: |
if(CreateFileInDirectory(fname,file)) // Could an entry for the new file in the rootdirectory be created? |
{ |
temp = (u16)cluster_temp; // remember the index of the free datacluster found for the directory entry. |
cluster_temp -=2; // Clusterposition is ((position in FAT)-2). first two entries in FAT are reserved. |
cluster_temp *= SectorsPerCluster; // Calculate relative sectorindex of first datacluster. |
file->start_cluster = (FirstDataCluster + cluster_temp); // Calculate absolute sectorposition of first datacluster. |
file->cluster_pointer = file->start_cluster; // start reading the file with the first sector of the first datacluster. |
if(CreateDirectoryEntry(&name[0],temp,file,_FILE)) // Could an entry for the new file in the rootdirectory be created? |
{ |
return(file); |
} |
} |
return(file); |
} |
else |
{ |
FreeFilePointer(file); // free the filepointer. |
file = NULL; |
} |
} |
else // file with mode 'r' not found |
{ |
FreeFilePointer(file); // free the filepointer. |
file = NULL; // file not found |
} |
} |
} |
return(0); |
return(file); |
} |
//________________________________________________________________________________________________________________________________________ |
// Funtion: fflush_(File *file); |
// |
255,21 → 247,14 |
u16 time=0; |
u16 date=0; |
#ifdef __USE_TIME_DATE_ATTRIBUTE // has the date and time attribute of the file to be set? |
time = (((rtctime.hour)<<11) | ((rtctime.minute)<<5) | rtctime.second); |
date = ((((rtctime.year)-1980) <<9) | ((rtctime.month) <<5) | rtctime.day); |
#endif |
if(file && file->mode =='a') |
if(file && ((file->mode =='a') || (file->mode =='w'))) |
{ |
if(file->byte_index > 0) // has data been added to the file? |
{ |
SDC_PutSector((u32)(file->cluster_pointer + file->sector_index),file->buffer); // save the data still in the buffer |
SDC_PutSector((u32)(file->cluster_pointer + file->sector_index),file->buffer);// save the data still in the buffer |
} |
SDC_GetSector((u32)file->directory_sector,file->buffer); // read the directoryentry for this file. |
SDC_GetSector((u32)file->directory_sector,file->buffer); // read the directoryentry for this file. |
DirectoryEntry = (struct DirEntry *)file->buffer; |
DirectoryEntry[file->directory_index].size = (u32) file->filesize; |
DirectoryEntry[file->directory_index].time = (u16) time; |
288,33 → 273,16 |
void fclose_(File *file) |
{ |
u8 cnt = 0; |
for(cnt=0;cnt<__MAX_FILES_USED;cnt++) |
if(file != NULL) |
{ |
if(&FilePointer[cnt] == file) // filepointer to be freed found? |
{ |
FilePointer[cnt].state = _UNUSED; |
} |
fflush_(file); // save buffercontent to the sdcard |
file->start_cluster = 0; // Sectorpointer to the first sector of the first datacluster of the file. |
file->cluster_pointer = 0; // Pointer to the cluster which is edited at the moment. |
file->sector_index = 0; // The sector which is edited at the moment (cluster_pointer + sector_index). |
file->byte_index = 0; // The bytelocation within the current sector (cluster_pointer + sector_index + byte_index). |
file->mode = 0; // mode of fileoperation (read,write) |
file->filesize = 0; // the size of the opend file in bytes. |
file->fileposition = 0; // pointer to a character within the file 0 < fileposition < filesize |
file->sector_in_buffer = 0; // the last sector read, wich is still in the sectorbuffer. |
file->directory_sector = 0; // the sectorposition where the directoryentry has been made. |
file->directory_index = 0; // the index to the directoryentry within the specified sector. |
file->attribute = 0; // the attribute of the file opened. |
fflush_(file); // save buffered data to the disk |
} |
FreeFilePointer(file); // and free the filepointer. |
} |
//________________________________________________________________________________________________________________________________________ |
// Funtion: s32 fread_(void *buffer, s32 size, s32 count, File *file); |
// Funtion: u32 fread_(void *buffer, s32 size, s32 count, File *file); |
// |
// Description: This function reads count objects of the specified size from the actual position of the file to the specified buffer. |
// |
324,12 → 292,12 |
u32 fread_(void *buffer, u32 size, u32 count, File *file) |
{ |
u32 object_cnt = 0; // count the number of objects read from the file. |
u32 object_cnt = 0; // count the number of objects read from the file. |
u32 object_size = 0; // count the number of bytes read from the actual object. |
u8 *buff_pnt = 0; // a pointer to the actual bufferposition. |
u8 success = 1; // no error occured during read operation to the file. |
u8 *buff_pnt = 0; // a pointer to the actual bufferposition. |
u8 success = 1; // no error occured during read operation to the file. |
buff_pnt = (u8 *) buffer; // cast the void pointer to an u8 * |
buff_pnt = (u8 *) buffer; // cast the void pointer to an u8 * |
while((object_cnt < count) && success) |
{ |
336,7 → 304,7 |
object_size = size; |
while((size > 0) && success) |
{ |
*buff_pnt = (u8) fgetchar_(file); // read a byte from the buffer to the opened file. |
*buff_pnt = (u8) fgetchar_(file); // read a byte from the buffer to the opened file. |
buff_pnt++; |
size--; |
} |
343,11 → 311,11 |
if(success) object_cnt++; |
} |
return(object_cnt); // return the number of objects succesfully read from the file |
return(object_cnt); // return the number of objects succesfully read from the file |
} |
//________________________________________________________________________________________________________________________________________ |
// Funtion: s32 fwrite_(void *buffer, s32 size, s32 count, File *file); |
// Funtion: u32 fwrite_(void *buffer, s32 size, s32 count, File *file); |
// |
// Description: This function writes count objects of the specified size from the buffer to the actual positon within the file. |
// |
357,12 → 325,12 |
u32 fwrite_(void *buffer, u32 size, u32 count, File *file) |
{ |
u32 object_cnt = 0; // count the number of objects written to the file. |
u32 object_cnt = 0; // count the number of objects written to the file. |
u32 object_size = 0; // count the number of bytes written from the actual object. |
u8 *buff_pnt = 0; // a pointer to the actual bufferposition. |
u8 success = 1; // no error occured during write operation to the file. |
u8 *buff_pnt = 0; // a pointer to the actual bufferposition. |
u8 success = 1; // no error occured during write operation to the file. |
buff_pnt = (u8 *) buffer; // cast the void pointer to an u8 * |
buff_pnt = (u8 *) buffer; // cast the void pointer to an u8 * |
while((object_cnt < count) && success) |
{ |
369,7 → 337,7 |
object_size = size; |
while((size > 0) && success) |
{ |
success = fputchar_(file, *buff_pnt); // write a byte from the buffer to the opened file. |
success = fputchar_(file, *buff_pnt); // write a byte from the buffer to the opened file. |
buff_pnt++; |
size--; |
} |
376,8 → 344,8 |
if(success) object_cnt++; |
} |
return(object_cnt); // return the number of objects succesfully written to the file |
} // (!!!!! objects and not bytes !!!!) |
return(object_cnt); // return the number of objects succesfully written to the file |
} // (!!!!! objects and not bytes !!!!) |
//________________________________________________________________________________________________________________________________________ |
// Funtion: s16 fseek_(File *, s32, s16) |
394,17 → 362,17 |
u32 temp = 0; |
//...................................................... |
if(origin == SEEK_SET) // Fileposition relative to the beginning of the file. |
if(origin == SEEK_SET) // Fileposition relative to the beginning of the file. |
{ |
fposition = 0; |
} |
//...................................................... |
else if(origin == SEEK_END) // Fileposition relative to the end of the file. |
else if(origin == SEEK_END) // Fileposition relative to the end of the file. |
{ |
fposition = (s32) file->filesize; |
} |
//...................................................... |
else if(origin == SEEK_CUR) // Fileposition relative to the current position of the file. |
else if(origin == SEEK_CUR) // Fileposition relative to the current position of the file. |
{ |
fposition = file->fileposition; |
} |
411,7 → 379,7 |
fposition += offset; |
if((fposition >= 0) && (fposition <= (s32)file->filesize)) // is the pointer still within the file? |
if((fposition >= 0) && (fposition <= (s32)file->filesize)) // is the pointer still within the file? |
{ |
retvalue = 0; |
file->sector_index = 0; |
428,14 → 396,14 |
} |
else |
{ |
file->byte_index=0; // reading at the beginning of new sector. |
file->sector_index++; // continue reading in next sector |
if(file->sector_index >= SectorsPerCluster) // When end of cluster is reached, the next datacluster has to be searched in the FAT. |
file->byte_index=0; // reading at the beginning of new sector. |
file->sector_index++; // continue reading in next sector |
if(file->sector_index >= SectorsPerCluster) // When end of cluster is reached, the next datacluster has to be searched in the FAT. |
{ |
if(file->fileposition < fposition) |
{ |
file->sector_index = 0; // start reading new cluster at first sector of the cluster. |
GetNextCluster(file); // Sets the clusterpointer of the file to the next datacluster. |
file->sector_index = 0; // start reading new cluster at first sector of the cluster. |
GetNextCluster(file); // Sets the clusterpointer of the file to the next datacluster. |
} |
} |
} |
443,7 → 411,7 |
if(file->byte_index) |
{ |
temp = (u32)((u32)file->cluster_pointer + (u32)file->sector_index); |
SDC_GetSector((u32)temp,file->buffer); // FileBuffer will be written at once at the end of the cluster and has to be updated. |
SDC_GetSector((u32)temp,file->buffer); // FileBuffer will be written at once at the end of the cluster and has to be updated. |
} |
} |
return(retvalue); |
452,8 → 420,8 |
//________________________________________________________________________________________________________________________________________ |
// Funtion: fgetchar_(File *file); |
// |
// Description: This function reads and returns one character from the specified file. Is the end of the actual sector reached the |
// next sector of the cluster is read. Is the last sector of the cluster read the next cluster will be searched in FAT. |
// Description: This function reads and returns one character from the specified file. |
// |
// Returnvalue: The function returns the character read from the specified memorylocation as u8 casted to s16 or EOF. |
//________________________________________________________________________________________________________________________________________ |
462,18 → 430,18 |
s16 c = EOF; |
u32 temp1; |
if(file->filesize > 0) // wen the end of the file is not reached, get the next character. |
if(((file->fileposition)+1) < file->filesize) // wen the end of the file is not reached, get the next character. |
{ |
temp1 = (u32)file->cluster_pointer; // calculate the adress of the next character to be read. |
temp1 = (u32)file->cluster_pointer; // calculate the adress of the next character to be read. |
temp1 += (u32)file->sector_index; |
if(file->sector_in_buffer != temp1) // Has the content of the buffer been modified and has to be updated? |
{ |
SDC_GetSector((u32)temp1,file->buffer); // Read the calculated cluster. |
SDC_GetSector((u32)temp1,file->buffer); // Read the calculated cluster. |
file->sector_in_buffer = (u32)temp1; |
} |
c = (s16) file->buffer[file->byte_index]; |
file->filesize--; // decrement the number of characters available. |
file->fileposition++; |
if(file->byte_index < 511) // continue reading from this sector until the end of the sector is reached. |
{ |
494,7 → 462,7 |
} |
//________________________________________________________________________________________________________________________________________ |
// Funtion: fputchar_(File *file); |
// Funtion: fputchar_(File *file, s8 *); |
// |
// Description: This function writes a byte to the specified file and takes care of writing the necessary FAT- Entries. |
// |
506,32 → 474,32 |
u32 ul_temp = 0; |
u8 retvalue = 1; |
if(file->sector_index >= SectorsPerCluster) // if end of the cluster is reached, find next free cluster |
if(file->sector_index >= SectorsPerCluster) // if end of the cluster is reached, find next free cluster |
{ |
file->sector_index = 0; |
if(!AppendCluster(file)) retvalue = 0; // append a new and free cluster at the end of the file. |
if(!AppendCluster(file)) retvalue = 0; // append a new and free cluster at the end of the file. |
} |
file->buffer[file->byte_index] = c; // write databyte into the buffer. The byte will be written to the device at once |
if(file->filesize == file->fileposition) file->filesize++; // a character has been written to the file so the size is inkremented but only when the character has been added at the end of the file. |
file->fileposition++; // the actual positon within the file. |
// if the buffer contains the complete sectordata. |
if(file->byte_index < 511) // if the end of this sector is not reached yet |
file->buffer[file->byte_index] = c; // write databyte into the buffer. The byte will be written to the device at once |
if(file->filesize == file->fileposition) file->filesize++; // a character has been written to the file so the size is inkremented but only when the character has been added at the end of the file. |
file->fileposition++; // the actual positon within the file. |
// if the buffer contains the complete sectordata. |
if(file->byte_index < 511) // if the end of this sector is not reached yet |
{ |
file->byte_index++; // the next byte will be written to the next byteposition in this sector. |
file->byte_index++; // the next byte will be written to the next byteposition in this sector. |
} |
else // otherwise the data in the sectorbuffer will be written to the device and the next sector will be selected. |
else // otherwise the data in the sectorbuffer will be written to the device and the next sector will be selected. |
{ |
ul_temp = (u32)file->cluster_pointer; |
ul_temp += (u32)file->sector_index; |
SDC_PutSector((u32)ul_temp,file->buffer); |
file->byte_index=0; // and the next byte will be written at the beginning of this new sector. |
file->byte_index=0; // and the next byte will be written at the beginning of this new sector. |
file->sector_index++; |
if(file->sector_index >= SectorsPerCluster) // if end of the cluster is reached, find next free cluster |
if(file->sector_index >= SectorsPerCluster) // if end of the cluster is reached, find next free cluster |
{ |
file->sector_index = 0; |
if(!AppendCluster(file)) retvalue = 0; // append a new and free cluster at the end of the file. |
if(!AppendCluster(file)) retvalue = 0; // append a new and free cluster at the end of the file. |
} |
} |
return(retvalue); |
538,9 → 506,9 |
} |
//________________________________________________________________________________________________________________________________________ |
// Funtion: fputs_(File *file); |
// Funtion: fputs_(File *file, s8 *string); |
// |
// Description: This function writes a string to the specified file. |
// Description: This function writes a zero terminated string to the specified file. |
// |
//________________________________________________________________________________________________________________________________________ |
557,11 → 525,11 |
} |
//________________________________________________________________________________________________________________________________________ |
// Funtion: fgets_(File *file); |
// Funtion: s8 * fgets_(s8 *string, s16 count, File *file) |
// |
// Description: This function reads a string from the file to the specifies string. |
// Description: This function reads a string from the file to the specifies string until EOF or end of line was detected.. |
// |
// Returnvalue: A pointer to the string written from the file. |
// Returnvalue: A pointer to the string or NULL if EOF was read from the file with no other characters before. |
//________________________________________________________________________________________________________________________________________ |
s8 * fgets_(s8 *string, s16 count, File *file) |
568,40 → 536,44 |
{ |
s16 buff_pnt = 0; |
s16 buff_tmp = 0; |
u8 state = 0; // Variable used for a statemachine to recognize the end of a line. |
s8 *retvalue = 0; |
while(count > 1) // read the count-1 characters from the file to the string. |
retvalue = string; |
while(count > 1) // read the count-1 characters from the file to the string. |
{ |
buff_tmp = fgetchar_(file); // read a character from the opened file. |
switch(state) |
buff_tmp = fgetchar_(file); // read a character from the opened file. |
if(buff_tmp == EOF) // is the end of the file reached, terminate the string with zero. |
{ |
case 0: |
if(buff_tmp == 0x0A)// state++; |
{ |
count = 1; |
} |
state = 0; |
if(buff_pnt != 0) // are there characters within the string? |
{ |
break; |
} |
else |
{ |
retvalue = NULL; // first character read was EOF -> return(NULL); |
break; |
} |
} |
else if(buff_tmp == 0x0A) // lf detected. |
{ |
string[buff_pnt] = (s8) buff_tmp; // add lf to the string. |
buff_pnt++; |
break; |
case 1: |
if(buff_tmp == 0x0A) |
{ |
count = 1; |
} |
state = 0; |
break; |
} |
if(buff_tmp == EOF) {buff_tmp = 0; count = 1;} // is the end of the file reached, terminate the string with zero. |
string[buff_pnt] = (s8) buff_tmp; |
count--; |
buff_pnt++; |
else |
{ |
string[buff_pnt] = (s8) buff_tmp; |
count--; |
buff_pnt++; |
} |
} |
string[buff_pnt] = 0; |
string[buff_pnt] = 0; // terminate string with zero |
return(string); |
} |
//________________________________________________________________________________________________________________________________________ |
// Funtion: u8 fexist_(u8*, File *file); |
// Funtion: u8 fexist_(u8*); |
// |
// Description: This function searches the specified file and returns 0 if the file was not found. |
// |
610,18 → 582,20 |
// 1 = file exists |
//________________________________________________________________________________________________________________________________________ |
u8 fexist_(u8 *fname) |
u8 fexist_(s8 *fname) |
{ |
File *file; |
file = fopen_(fname,'r'); // try to open the specified file. |
if((file = fopen_(fname,'r')) != 0) |
if(file != NULL) |
{ |
fclose_(file); |
return(1); |
FreeFilePointer(file); // Free the filepoint // free the filepointer |
return(1); // file was found so return(1); |
} |
else |
{ |
return(0); |
return(0); // file not found return(0); |
} |
} |
638,7 → 612,7 |
u32 fat_pointer = 0; |
u32 fat_sector_offset = 0; |
u32 ul_tmp = 0; |
u8 retvalue = 0; // no new cluster found yet. |
u8 retvalue = 0; // no new cluster found yet. |
if((file->cluster_pointer >= RootDirectory) && (file->cluster_pointer < (RootDirectory + 31))) |
655,9 → 629,9 |
fat_sector_offset = (fat_sector_offset>>8); // and the position within the sector. |
SDC_GetSector((u32)(FileAllocationTable + fat_sector_offset),file->buffer); |
file->sector_in_buffer = (FileAllocationTable + fat_sector_offset); // Mark that new sector has been read. |
file->sector_in_buffer = (FileAllocationTable + fat_sector_offset); // Mark that new sector has been read. |
ul_tmp = (u32)file->buffer[((fat_pointer << 1)+1)]; // Read next sector information from calculated clusterposition. |
ul_tmp = (u32)file->buffer[((fat_pointer << 1)+1)]; // Read next sector information from calculated clusterposition. |
ul_tmp = (ul_tmp << 8); |
ul_tmp |= (u32)file->buffer[(fat_pointer << 1)]; |
ul_tmp -=2; // next datacluster is clusterposition in fat - 2. |
666,7 → 640,7 |
if(ul_tmp < 0xfff7) // has a new cluster been read or was the end of the fat reached? |
{ |
file->cluster_pointer = (u32) ul_tmp; // continue reading the file at the beginning of new datacluster. |
file->cluster_pointer = (u32) ul_tmp; // continue reading the file at the beginning of new datacluster. |
retvalue = 1; // a new cluster was found. |
} |
} |
683,29 → 657,29 |
u16 FindNextFreeCluster(File *file) |
{ |
u32 fat_pointer = 0; // Pointer to the first sector of the FAT. |
u32 ul_tmp = 0; // temporary variable used to calculate a sectornumber. |
u16 fat_sector_offset = 0; // index to a sector within the FAT. |
u16 fat_entry = 0; // index to an fatentry within the actual sector (256 fatentries are possible within one sector). |
u16 free_cluster = 0; // a pointer to the first sector of the next free cluster. |
u32 fat_pointer = 0; // Pointer to the first sector of the FAT. |
u32 ul_tmp = 0; // temporary variable used to calculate a sectornumber. |
u16 fat_sector_offset = 0; // index to a sector within the FAT. |
u16 fat_entry = 0; // index to an fatentry within the actual sector (256 fatentries are possible within one sector). |
u16 free_cluster = 0; // a pointer to the first sector of the next free cluster. |
fat_pointer = (u32) FileAllocationTable; // start searching for empty cluster at the beginning of the fat. |
// if the end of the fat is not reached yet and no free cluster has been found |
fat_pointer = (u32) FileAllocationTable; // start searching for empty cluster at the beginning of the fat. |
// if the end of the fat is not reached yet and no free cluster has been found |
while((fat_sector_offset < SectorsPerFat) && (!free_cluster)) |
{ |
ul_tmp = (u32) ((u32)fat_pointer + (u32)fat_sector_offset); |
SDC_GetSector((u32)ul_tmp,file->buffer); // read next sector of FAT. |
file->sector_in_buffer = ul_tmp; // remember the number of the sector in FileBuffer. |
SDC_GetSector((u32)ul_tmp,file->buffer); // read next sector of FAT. |
file->sector_in_buffer = ul_tmp; // remember the number of the sector in FileBuffer. |
Fat = (struct FatEntry *)file->buffer; |
for(fat_entry=0;fat_entry<256;fat_entry++) // look for an free cluster at all entries in this sector of the fat. |
for(fat_entry=0;fat_entry<256;fat_entry++) // look for an free cluster at all entries in this sector of the fat. |
{ |
if(Fat[fat_entry].next_cluster == 0x0000) // empty cluster found!! |
if(Fat[fat_entry].next_cluster == 0x0000) // empty cluster found!! |
{ |
Fat[fat_entry].next_cluster = 0xffff; // mark this fat-entry as used and save it to the device. |
Fat[fat_entry].next_cluster = 0xffff; // mark this fat-entry as used and save it to the device. |
SDC_PutSector((u32)file->sector_in_buffer,file->buffer); |
free_cluster = fat_entry; // the relative position of the free cluster found in this sector of the FAT. |
free_cluster += (fat_sector_offset << 8); // calculate the absolute position of the free cluster in the FAT; |
fat_entry = 256; // terminate the search for a free cluster in this sector. |
free_cluster = fat_entry; // the relative position of the free cluster found in this sector of the FAT. |
free_cluster += (fat_sector_offset << 8); // calculate the absolute position of the free cluster in the FAT; |
fat_entry = 256; // terminate the search for a free cluster in this sector. |
} |
} |
fat_sector_offset++; |
727,15 → 701,15 |
u32 fat_pointer = 0; |
u8 retvalue = 0; |
free_cluster = FindNextFreeCluster(file); // the next free cluster found on the disk. |
if(free_cluster) retvalue = 1; // A free cluster was found and can be added to the end of the file. |
fat_pointer = FileAllocationTable; // Set Pointer to the beginnig of the FAT. |
fat_pointer += (u32)((u32)GetFatClusterOffset(file) >> 8); // find the sector in the FAT with 256 entries per sector. |
free_cluster = FindNextFreeCluster(file); // the next free cluster found on the disk. |
if(free_cluster) retvalue = 1; // A free cluster was found and can be added to the end of the file. |
fat_pointer = FileAllocationTable; // Set Pointer to the beginnig of the FAT. |
fat_pointer += (u32)((u32)GetFatClusterOffset(file) >> 8); // find the sector in the FAT with 256 entries per sector. |
SDC_GetSector(fat_pointer,file->buffer); |
Fat = (struct FatEntry *)file->buffer; |
Fat[GetFatSectorIndex(file)].next_cluster = free_cluster; // append the free cluster to the end of the file in the FAT. |
SDC_PutSector((u32)fat_pointer,file->buffer); // save the modified sector to the FAT. |
Fat[GetFatSectorIndex(file)].next_cluster = free_cluster; // append the free cluster to the end of the file in the FAT. |
SDC_PutSector((u32)fat_pointer,file->buffer); // save the modified sector to the FAT. |
fat_pointer = (u32)free_cluster; |
fat_pointer -= 2; |
742,11 → 716,57 |
fat_pointer *= SectorsPerCluster; |
fat_pointer += FirstDataCluster; |
file->cluster_pointer = fat_pointer; // continue wrtiting to the file in the new and free datacluster. |
return(retvalue); // return 1 when a new cluster was appended to the file |
file->cluster_pointer = fat_pointer; // continue wrtiting to the file in the new and free datacluster. |
return(retvalue); // return 1 when a new cluster was appended to the file |
} |
//________________________________________________________________________________________________________________________________________ |
// Funtion: void DeleteClusterChain(u16 startcluster); |
// |
// Description: This function frees all the clusters used for file from the fat. |
// |
// Returnvalue: none |
//________________________________________________________________________________________________________________________________________ |
void DeleteClusterChain(u16 startcluster) |
{ |
u16 fat_index = 0; |
u16 fat_sector_offset = 0; |
u32 sector_in_buffer = 0; |
u32 ul_temp = 0; |
u8 buffer[512]; |
fat_index = (startcluster % 0x100); // Calculate the sector within the cluster. |
fat_sector_offset = (startcluster >> 8); // and the position within the sector. |
ul_temp = (u32)(FileAllocationTable + fat_sector_offset); |
do |
{ |
if(sector_in_buffer != ul_temp) |
{ |
sector_in_buffer = ul_temp; |
SDC_GetSector(ul_temp,buffer); |
} |
Fat = (struct FatEntry *)buffer; |
startcluster = Fat[fat_index].next_cluster; |
Fat[fat_index].next_cluster = 0x0000; // free the cluster within the fat. |
fat_index = (startcluster % 0x100); // Calculate the sector within the cluster. |
fat_sector_offset = (startcluster >> 8); // and the position within the sector. |
ul_temp = (u32)(FileAllocationTable + fat_sector_offset); |
if((sector_in_buffer != ul_temp) || (startcluster == 0xffff)) |
{ |
SDC_PutSector(sector_in_buffer,buffer); |
} |
} |
while(startcluster != 0xffff); // last cluster has been deleted. |
} |
//________________________________________________________________________________________________________________________________________ |
// Funtion: u16 GetFatClusterIndex(File *file); |
// |
// Description: This function returns the clusterindex of the cluster specified by file->cluster_pointer of the specified file. |
757,9 → 777,9 |
{ |
u32 fat_sector_offset = 0; |
fat_sector_offset = ((file->cluster_pointer) - (FirstDataCluster)); // Calculate index of actual cluster in FAT. |
fat_sector_offset = ((file->cluster_pointer) - (FirstDataCluster)); // Calculate index of actual cluster in FAT. |
fat_sector_offset /= SectorsPerCluster; |
fat_sector_offset += 2; // In Fat16 clusterpositions have an offset of two. |
fat_sector_offset += 2; // In Fat16 clusterpositions have an offset of two. |
return((u16)fat_sector_offset); |
} |
776,13 → 796,13 |
u16 fat_pointer = 0; |
fat_pointer = GetFatClusterOffset(file); |
fat_pointer = fat_pointer % 0x100; // Calculate the clusterposition in the fat |
fat_pointer = fat_pointer % 0x100; // Calculate the clusterposition in the fat |
return(fat_pointer); |
} |
//________________________________________________________________________________________________________________________________________ |
// Funtion: u16 CreateDirectoryEntry(u8 *, u16, u8 attrib) |
// Funtion: u16 CreateFileInDirectory(u8 *, File *) |
// |
// Description: This function looks for the next free position in the directory and creates an entry. The type of an directoryentry is |
// specified by the attribute. |
794,88 → 814,110 |
// bit5: volume |
//________________________________________________________________________________________________________________________________________ |
u8 CreateDirectoryEntry(u8 *fname, u16 cluster, File *file,u8 attrib) |
u8 CreateFileInDirectory(s8 *fname, File *file) |
{ |
u16 rootentry = 0; // index to an entry in the rootdirectory. |
u16 cnt_enries_searched = 0; // count the number of rootentries which have been searched already. |
u8 i = 0; |
u16 sector_offset = 0; // index to the sector of the Rootentry which is searched momentarily |
u8 retvalue = 0; |
u16 rootentry = 0; // index to an entry in the rootdirectory. |
u16 cnt_enries_searched = 0; // count the number of rootentries which have been searched already. |
u8 i = 0; |
u16 sector_offset = 0; // index to the sector of the Rootentry which is searched momentarily |
u8 retvalue = 0; |
u32 cluster_temp = 0; |
u16 cluster = 0; |
s8 name[11] = " "; |
SeperateFileName(fname,name); |
cluster_temp = (u32)FindNextFreeCluster(file); // the next free cluster on the disk. |
// directory starts at sector specified by dir_sector. This can be the rootdirectory or any other directory. |
do |
{ // search the next 16 rootentries in this sector of the roordirectory. |
rootentry=0; |
SDC_GetSector((u32)(RootDirectory + sector_offset),file->buffer); // Read the Rootdirectory. |
DirectoryEntry = (struct DirEntry *)file->buffer; |
while((rootentry<16) && (!retvalue)) |
{ |
if((DirectoryEntry[rootentry].attribute == 0) || (DirectoryEntry[rootentry].attribute == 0xE5)) // empty directory entry found |
if(cluster_temp) // if a free cluster is available: |
{ |
cluster = (u16)cluster_temp; // remember the index of the free datacluster found for the directory entry. |
cluster_temp -=2; // Clusterposition is ((position in FAT)-2). first two entries in FAT are reserved. |
cluster_temp *= SectorsPerCluster; // Calculate relative sectorindex of first datacluster. |
file->start_cluster = (FirstDataCluster + cluster_temp); // Calculate absolute sectorposition of first datacluster. |
file->cluster_pointer = file->start_cluster; // start reading the file with the first sector of the first datacluster. |
// directory starts at sector specified by dir_sector. This can be the rootdirectory or any other directory. |
do |
{ // search the next 16 rootentries in this sector of the roordirectory. |
rootentry=0; |
SDC_GetSector((u32)(CWD + sector_offset),file->buffer); // Read the Rootdirectory. |
DirectoryEntry = (struct DirEntry *)file->buffer; |
while((rootentry<16) && (!retvalue)) |
{ |
for(i=0;i<11;i++) DirectoryEntry[rootentry].name[i] = fname[i]; // Kopie the filename and the file extension to the directoryentry. |
DirectoryEntry[rootentry].attribute = attrib; // Set the fileattribute to archive to reserve the directoryentry. |
DirectoryEntry[rootentry].startcluster = cluster; // copy the location of the first datacluster to the directoryentry. |
DirectoryEntry[rootentry].size = 0; // the new createted file has no content yet. |
file->directory_sector = (u32) (RootDirectory + sector_offset); |
file->directory_index = (u8) rootentry; |
retvalue = 1; |
SDC_PutSector((u32)(RootDirectory + sector_offset),file->buffer); |
} |
rootentry++; |
cnt_enries_searched++; |
if((DirectoryEntry[rootentry].attribute == 0) || (DirectoryEntry[rootentry].attribute == 0xE5)) // empty directory entry found |
{ |
for(i=0;i<11;i++) DirectoryEntry[rootentry].name[i] = name[i];// Kopie the filename and the file extension to the directoryentry. |
DirectoryEntry[rootentry].attribute = _FILE; // Set the fileattribute to archive to reserve the directoryentry. |
DirectoryEntry[rootentry].startcluster = cluster; // copy the location of the first datacluster to the directoryentry. |
DirectoryEntry[rootentry].size = 0; // the new createted file has no content yet. |
file->directory_sector = (u32) (CWD + sector_offset); |
file->directory_index = (u8) rootentry; |
retvalue = 1; |
SDC_PutSector((u32)(CWD + sector_offset),file->buffer); |
} |
rootentry++; |
cnt_enries_searched++; |
} |
if(!retvalue) // file not found in this sector so take next sector. |
{ |
rootentry = 0; |
sector_offset++; |
} |
} |
if(!retvalue) // file not found in this sector so take next sector. |
{ |
rootentry = 0; |
sector_offset++; |
} |
while((cnt_enries_searched< PossibleRootEntries) && (!retvalue)); |
} |
while((cnt_enries_searched< PossibleRootEntries) && (!retvalue)); |
return(retvalue); // return 1 if file has been created otherwise return 0. |
return(retvalue); // return 1 if file has been created otherwise return 0. |
} |
//________________________________________________________________________________________________________________________________________ |
// Funtion: u16 SeekDirectoryEntry(u8*, File *, u8) |
// Funtion: u16 SeekFileInDirectory(s8 *fname, File *) |
// |
// Description: this function searches all possible rootentries until the file or directory is found or the end of the rootdirectory is reached |
// Description: this function searches all possible entries withint the actual directory for the specified object. |
// |
// Returnvalue: This function returns 1 if the directoryentry specified was found. |
//________________________________________________________________________________________________________________________________________ |
u8 SeekDirectoryEntry(u8 *fname, File *file) |
u8 SeekFileInDirectory(s8 *fname, File *file) |
{ |
u16 rootentry=0; |
u16 end_of_directory_not_reached = 0; // the directory has been read completely without a result. |
u8 i=0; |
u16 end_of_directory_not_reached = 0; // the directory has been read completely without a result. |
u8 i=0; |
u8 retvalue = 0; |
u32 cluster_temp = 0; |
u16 cnt=0; |
s8 name[11] = " "; |
SeperateFileName(fname,name); |
file->cluster_pointer = CWD; // start looking for the file in the actual directory. |
// directory starts at sector specified by dir_sector. This can be the rootdirectory or any other directory. |
// directory starts at sector specified by dir_sector. This can be the rootdirectory or any other directory. |
do |
{ // search the next 16 rootentries in this sector of the roordirectory. |
{ // search the next 16 rootentries in this sector of the roordirectory. |
rootentry=0; |
SDC_GetSector((u32) file->cluster_pointer,file->buffer); // Read the Rootdirectory. |
SDC_GetSector((u32) file->cluster_pointer,file->buffer); // Read the Rootdirectory. |
DirectoryEntry = (struct DirEntry *)file->buffer; |
while((!retvalue)&&(rootentry<16)) |
{ |
cnt++; |
i=0; |
while((i<10)&&(DirectoryEntry[rootentry].name[i] == fname[i])) |
if(DirectoryEntry[rootentry].name[0] != 0xe5) // ignore deleted items. |
{ |
i++; |
while((i<=10)&&(DirectoryEntry[rootentry].name[i] == name[i])) |
{ |
i++; |
} |
} |
if((i==10) && (DirectoryEntry[rootentry].attribute == file->attribute)) // entry found!! -> reading startcluster of entry from offset 26. |
if((i==11) && (DirectoryEntry[rootentry].attribute & _FILE)) // entry found!! -> reading startcluster of entry from offset 26. |
{ |
cluster_temp = (u32)DirectoryEntry[rootentry].startcluster; |
cluster_temp -=2; // Clusterposition is ((position in FAT)-2). first two entries in FAT are reserved. |
cluster_temp *= (u32)SectorsPerCluster; // Calculate positon of first cluster. |
cluster_temp -=2; // Clusterposition is ((position in FAT)-2). first two entries in FAT are reserved. |
cluster_temp *= (u32)SectorsPerCluster; // Calculate positon of first cluster. |
file->start_cluster = (FirstDataCluster + cluster_temp); |
file->directory_sector = (u32) file->cluster_pointer; |
file->cluster_pointer = file->start_cluster; // start reading the file with the first cluster. |
file->cluster_pointer = file->start_cluster; // start reading the file with the first cluster. |
file->filesize = (u32) DirectoryEntry[rootentry].size; |
file->directory_index = (u8) rootentry; |
retvalue = 1; |
882,7 → 924,7 |
} |
rootentry++; |
} |
if(!retvalue) // file not found in this sector so take next sector. |
if(!retvalue) // file not found in this sector so take next sector. |
{ |
end_of_directory_not_reached = GetNextCluster(file); |
} |
891,117 → 933,609 |
return(retvalue); |
} |
//________________________________________________________________________________________________________________________________________ |
// Funtion: void ScanSubDirectories(u8*, File *file); |
// Funtion: void SeperateFileName(u8*); |
// |
// Description: This function scans the filename for subdirectories and changes the directory until the last directory is reached. |
// here the specified file is searched. |
// Description: This function seperates the filename and the fileattribute and brings them into the needed format ('test.txt' -> 'TEST TXT'); |
// |
// Returnvalue: |
//________________________________________________________________________________________________________________________________________ |
u8 ScanSubDirectories(u8 *fname, File *file) |
void SeperateFileName(s8 *fname, s8 *name) |
{ |
u8 readpointer = 0; // pointer to read a character within the filepath. |
u8 writepointer = 0; // pointer to write a character into the string dirname. |
u8 dircnt = 0; // the number of subdirectories found in filepath. |
u8 dirname[11]; // temporary variable containing the name of a directory within the filepath. |
u8 retvalue = 1; // no error opening a subdirectory occured yet. |
u8 cnt = 0; // maximun number of characters in a path is 256; |
u8 readpointer = 0; |
u8 writepointer = 0; |
u8 attribute = 1; |
u8 i = 0; |
while((writepointer<=10) && (fname[readpointer]!=0)) // the rootdirectoryentry is 8bytes for filename and 3bytes for fileattribute. |
{ // the filename in the rootdirectory is in the format "TEST TXT" without the dot. |
if(fname[readpointer]=='.') // seperating filename and attribute. |
{ |
if(attribute) // is the filename "." or ".." ? |
{ |
name[writepointer] = fname[readpointer]; |
readpointer++; |
writepointer++; |
} |
else |
{ |
if(fname[(readpointer-1)] != '*') |
{ |
for(i=writepointer;i<8;i++) |
{ |
name[i] = ' '; |
} |
} |
readpointer++; |
writepointer = 8; |
} |
} |
else if(fname[readpointer] == '*') // wildcard found within the filename + extension. |
{ |
if(writepointer < 8) // in extension. |
{ |
readpointer++; |
writepointer = 8; |
} |
else // in filename. |
{ |
writepointer = 11; // jump to the end of the string to terminate this function. |
} |
attribute = 0; |
} |
else |
{ |
if((fname[readpointer]>96) && (fname[readpointer]<123)) |
{ |
name[writepointer]=(fname[readpointer] - 32); // all characters must be upper case. |
} |
else |
{ |
name[writepointer]=fname[readpointer]; |
} |
readpointer++; |
writepointer++; |
attribute = 0; |
} |
} |
} |
while((fname[readpointer]!=0) && (cnt < 255)) // search the string until the end is reached. |
//________________________________________________________________________________________________________________________________________ |
// Funtion: File * ReserveFilePointer_(void); |
// |
// Description: This function looks for a free filepointer and reserves it. |
// |
// |
// Return: NULL = faild to reserve a filepointer |
// otherwise filepointer |
//________________________________________________________________________________________________________________________________________ |
File * ReserveFilePointer(void) |
{ |
File *file; |
file = NULL; |
u8 temp; |
for(temp = 0;temp<__MAX_FILES_USED;temp++) |
{ |
cnt++; |
if((fname[readpointer] == '/') && readpointer) // subdirectory found. ignore first "/" as directory. |
if(FilePointer[temp].state == _UNUSED) // free filepointer found? |
{ |
dircnt++; // count the number of subdirectories found within the filepath. |
file = &FilePointer[temp]; |
FilePointer[temp].state = _USED; // mark as used. |
FilePointer[temp].mode = 0; // type of access (read/write) not defined yet. |
FilePointer[temp].start_cluster = 0; // Sectorpointer to the first sector of the first datacluster of the file. |
FilePointer[temp].cluster_pointer = 0; // Pointer to the cluster which is edited at the moment. |
FilePointer[temp].sector_index = 0; // The sector which is edited at the moment (cluster_pointer + sector_index). |
FilePointer[temp].byte_index = 0; // The bytelocation within the current sector (cluster_pointer + sector_index + byte_index). |
FilePointer[temp].filesize = 0; // the size of the opend file in bytes. |
FilePointer[temp].fileposition = 0; // pointer to a character within the file 0 < fileposition < filesize |
FilePointer[temp].sector_in_buffer = 0; // the last sector read, wich is still in the sectorbuffer. |
FilePointer[temp].directory_sector = 0; // the sectorposition where the directoryentry has been made. |
FilePointer[temp].directory_index = 0; // the index to the directoryentry within the specified sector. |
FilePointer[temp].attribute = 0; // the attribute of the file opened. |
break; |
} |
readpointer++; |
} |
return(file); |
} |
//________________________________________________________________________________________________________________________________________ |
// Funtion: void FreeFilePointer_(File *); |
// |
// Description: This function free's the filepointer by marking it as unused. |
// |
// |
// Return: none |
// |
//________________________________________________________________________________________________________________________________________ |
void FreeFilePointer(File *file) |
{ |
u8 cnt = 0; |
for(writepointer=0;writepointer<10;writepointer++) dirname[writepointer] = ' '; |
writepointer = 0; |
readpointer = 0; // start scanning the string at the beginning. |
for(cnt=0;cnt<__MAX_FILES_USED;cnt++) // Is the filepointeradress vaild? |
{ |
if(&FilePointer[cnt] == file) // filepointer found therefore it must be valid |
{ |
FilePointer[cnt].state = _UNUSED; // and can be marked as unused. |
} |
} |
} |
file->cluster_pointer = RootDirectory; // always start searching in the rootdirectory. |
file->attribute = _DIRECTORY; // the attribute of the item to be searched in the specified directory. |
//________________________________________________________________________________________________________________________________________ |
// Funtion: void DelteDirectoryEntry(Find *) |
// |
// Description: This function deletes the directoryentry of the specified item. |
// |
// |
// returnvalue: 1 if the directory could be created. |
//________________________________________________________________________________________________________________________________________ |
void DeleteDirectoryEntry(Find *item) |
{ |
u8 buffer[512]; |
while(dircnt && retvalue) // scan all subdirectories found before. |
SDC_GetSector((u32) item->cluster_pointer,buffer); // Read the Rootdirectory. |
DirectoryEntry = (struct DirEntry *)buffer; |
DirectoryEntry[(item->directory_index)-1].attribute = 0; // free the directoryentry. |
DirectoryEntry[(item->directory_index)-1].name[0] = 0xE5; // free the directoryentry. |
SDC_PutSector((u32) item->cluster_pointer,buffer); // Read the Rootdirectory. |
} |
//________________________________________________________________________________________________________________________________________ |
// Funtion: u8 CreateSubDirectory(u8 *) |
// |
// Description: This function creates an directory within the directory specified by CWD |
// |
// |
// returnvalue: 1 if the directory could be created. |
//________________________________________________________________________________________________________________________________________ |
u8 CreateSubDirectory(s8 *fname) |
{ |
u16 index = 0; // index to an entry in the rootdirectory. |
u16 cnt_entries_searched = 0; // count the number of rootentries which have been searched already. |
u16 i = 0; |
u16 sector_offset = 0; // index to the sector of the entry which is searched momentarily |
u8 retvalue = 0; |
u32 cluster_temp = 0; |
u16 cluster = 0; |
File file; |
s8 name[11] = {" "}; |
SeperateFileName(fname,name); |
cluster_temp = (u32)FindNextFreeCluster(&file); // the next free cluster on the disk. |
if(cluster_temp) // if a free cluster is available: |
{ |
if(fname[readpointer] != '/') // is the end of the subdirectory entry not reached yet? |
cluster = (u16)cluster_temp; // remember the index of the free datacluster found for the directory entry. |
cluster_temp -=2; // Clusterposition is ((position in FAT)-2). first two entries in FAT are reserved. |
cluster_temp *= SectorsPerCluster; // Calculate relative sectorindex of first datacluster. |
file.start_cluster = (FirstDataCluster + cluster_temp); // Calculate absolute sectorposition of first datacluster. |
file.cluster_pointer = file.start_cluster; // start reading the file with the first sector of the first datacluster. |
// -Initialise new cluster to zero-------------------------------------------------------- |
for(i=0;i<512;i++) |
{ |
if((fname[readpointer]>96) && (fname[readpointer]<123)) |
{ // all characters must be upper case. |
dirname[writepointer]=(fname[readpointer] - 32); |
file.buffer[i] = 0; // initialise buffer to zero |
} |
for(sector_offset=0;sector_offset<SectorsPerCluster;sector_offset++) // initialise all sectors of new cluster with buffer. |
{ |
SDC_PutSector((u32)(file.start_cluster + sector_offset),file.buffer); // save the initialised sector to the card. |
} |
// -Create directoryentry "." ------------------------------------------------------------- |
DirectoryEntry = (struct DirEntry *)file.buffer; |
DirectoryEntry[0].name[0] = '.'; |
DirectoryEntry[0].attribute = _DIRECTORY; |
DirectoryEntry[0].startcluster = cluster; |
// -Create directoryentry "." ------------------------------------------------------------- |
DirectoryEntry[1].name[0] = '.'; |
DirectoryEntry[1].name[1] = '.'; |
DirectoryEntry[1].attribute = _DIRECTORY; |
if(CWD == RootDirectory) |
{ |
DirectoryEntry[1].startcluster = 0; |
} |
else |
{ |
cluster_temp = (CWD - FirstDataCluster); |
cluster_temp /= SectorsPerCluster; |
cluster_temp -= 2; |
DirectoryEntry[1].startcluster = (u16) cluster_temp; |
} |
SDC_PutSector((u32) file.start_cluster,file.buffer); // save the initialised sector to the card. |
// -create directoryentry within the cwd -------------------------------------------------- |
sector_offset = 0; |
cnt_entries_searched = 0; |
do |
{ // search the next 16 rootentries in this sector of the roordirectory. |
index=0; |
SDC_GetSector((u32)(CWD + sector_offset),file.buffer); // Read the actual directory. |
DirectoryEntry = (struct DirEntry *)file.buffer; |
while((index<16) && (!retvalue)) |
{ |
if((DirectoryEntry[index].attribute == 0) || (DirectoryEntry[index].attribute == 0xE5)) // empty directory entry found |
{ |
for(i=0;i<11;i++) DirectoryEntry[index].name[i] = name[i]; // Kopie the filename and the file extension to the directoryentry. |
DirectoryEntry[index].attribute = _DIRECTORY; // Set the fileattribute to archive to reserve the directoryentry. |
DirectoryEntry[index].startcluster = cluster; // copy the location of the first datacluster to the directoryentry. |
DirectoryEntry[index].size = 0; // the new createted file has no content yet. |
file.directory_sector = (u32) (CWD + sector_offset); |
file.directory_index = (u8) index; |
retvalue = 1; |
SDC_PutSector((u32)(CWD + sector_offset),file.buffer); |
} |
index++; |
cnt_entries_searched++; |
} |
else |
if(!retvalue) // file not found in this sector so take next sector. |
{ |
dirname[writepointer]=fname[readpointer]; |
} |
writepointer++; |
} |
else |
{ |
dircnt--; |
if(!(SeekDirectoryEntry(dirname, file))) // was the seperated subdirectory not found? |
index = 0; |
sector_offset++; |
} |
} |
while((cnt_entries_searched< PossibleRootEntries) && (!retvalue)); |
} |
return(retvalue); // return 1 if file has been created otherwise return 0. |
} |
//________________________________________________________________________________________________________________________________________ |
// Funtion: u16 SeekSubDirectory(s8 *fname) |
// |
// Description: looks for the specified directory within the CWD. |
// |
// Returnvalue: If the specified directory was found the startcluster is returned. otherwise 0. |
//________________________________________________________________________________________________________________________________________ |
u16 SeekSubDirectory(s8 *fname) |
{ |
u16 index = 0; |
u16 end_of_directory_not_reached = 0; // the directory has been read completely without a result. |
u8 i = 0; |
u16 cluster_temp = 0; |
s8 name[11] = " "; |
File file; |
SeperateFileName(fname,name); |
file.cluster_pointer = CWD; // start looking for the file in the actual directory. |
file.start_cluster = CWD; // start looking for the file in the actual directory. |
// directory starts at sector specified by dir_sector. This can be the rootdirectory or any other directory. |
do |
{ // search the next 16 rootentries in this sector of the roordirectory. |
index=0; |
SDC_GetSector((u32) file.cluster_pointer,file.buffer); // Read the Rootdirectory. |
DirectoryEntry = (struct DirEntry *)file.buffer; |
while((!cluster_temp)&&(index<16)) |
{ |
i=0; |
if(DirectoryEntry[index].name[0] != 0xe5) // ignore deleted items. |
{ |
retvalue = 0; // leave the function with return(0) otherwise continue with the next subdirectory until all directories have been searched. |
while((i<=10)&&(DirectoryEntry[index].name[i] == name[i])) |
{ |
i++; |
} |
} |
for(writepointer=0;writepointer<10;writepointer++) dirname[writepointer] = ' '; |
writepointer = 0; |
if((i==11) && (DirectoryEntry[index].attribute & _DIRECTORY)) // entry found!! -> reading startcluster of entry from offset 26. |
{ |
cluster_temp = (u16)DirectoryEntry[index].startcluster; |
} |
index++; |
} |
readpointer++; |
if(!cluster_temp) // file not found in this sector so take next sector. |
{ |
end_of_directory_not_reached = GetNextCluster(&file); |
} |
} |
file->attribute = _FILE; // All subdirectories have been searched. the next thing to find is the specified file. |
while((end_of_directory_not_reached) && (!cluster_temp)); |
return(cluster_temp); |
} |
//________________________________________________________________________________________________________________________________________ |
// Funtion: u8 mkdir_(u8 *) |
// |
// Description: This function checks if the directory to be created already exists. If not the directory will be created. |
// |
// |
// returnvalue: 1 if the directory could be created. |
//________________________________________________________________________________________________________________________________________ |
u8 mkdir_(s8 *fname) |
{ |
u8 retvalue = 0; |
retvalue = SeekSubDirectory(fname); // check wether the specified directory already exists. |
if(!retvalue) |
{ |
CreateSubDirectory(fname); // if directory doesn't exist, create it. |
retvalue = 1; |
} |
else |
{ |
retvalue = 0; |
} |
return(retvalue); |
} |
//________________________________________________________________________________________________________________________________________ |
// Funtion: void SeperateFileName(u8*); |
// Funtion: u8 chdir_(u8 *) |
// |
// Description: This function seperates the filename and the fileattribute and brings them into the needed format ('test.txt' -> 'TEST TXT'); |
// Description: This function changes the CWD to the directory specified. |
// |
// |
// returnvalue: 1 if the directory could be changed. |
//________________________________________________________________________________________________________________________________________ |
void SeperateFileName(u8 *fname, u8 *name) |
u8 chdir_(s8 *fname) |
{ |
u8 readpointer = 0; |
u8 writepointer = 0; |
u8 dircnt = 0; // the number of subdirectories found in filepath. |
u8 fileindex = 0; // the position in the filenamestring where the last "/" is found. |
u8 retvalue = 0; |
s8 name[11] = {" "}; |
while(fname[readpointer]!=0) // search the string until the end is reached. |
u32 ultemp = 0; |
SeperateFileName(fname,name); |
ultemp = (u32)SeekSubDirectory(name); |
if(ultemp >= 2) |
{ |
if((fname[readpointer] == '/') && readpointer) // subdirectory found. ignore first "/" as directory. |
ultemp -=2; // Clusterposition is ((position in FAT)-2). first two entries in FAT are reserved. |
ultemp *= SectorsPerCluster; // Calculate relative sectorindex of first datacluster. |
ultemp += FirstDataCluster; |
CWD = ultemp; |
retvalue = 1; |
} |
else |
{ |
CWD = RootDirectory; |
retvalue = 1; |
} |
return(retvalue); |
} |
//________________________________________________________________________________________________________________________________________ |
// Funtion: u8 FindItem(s8 *fname, Find *) |
// |
// Description: finds an item (file or directory) within common working directory (cwd). Wildcards '*' or '?' will be considered. |
// |
// Returnvalue: If an item was found this function returns '1' else '0'. |
//________________________________________________________________________________________________________________________________________ |
u8 FindItem(Find *item) |
{ |
u16 index = 0; |
u16 end_of_directory_not_reached = 0; // the directory has been read completely without a result. |
u8 i = 0; |
u8 readpointer = 0; |
u8 writepointer = 0; |
u8 retvalue = 0; |
File file; |
file.cluster_pointer = item->cluster_pointer; |
file.start_cluster = item->cluster_pointer; |
index = item->directory_index; |
// directory starts at sector specified by dir_sector. This can be the rootdirectory or any other directory. |
do |
{ // search the next 16 rootentries in this sector of the roordirectory. |
SDC_GetSector((u32) file.cluster_pointer,file.buffer); // Read the Rootdirectory. |
DirectoryEntry = (struct DirEntry *)file.buffer; |
while((!retvalue)&&(index<16)) |
{ |
dircnt++; // subdirectory entry found. |
fileindex = (readpointer + 1); // store the index of the last slash found as the beginning of the filename. |
i=0; |
if(DirectoryEntry[index].name[0] != 0xe5) // ignore deleted items. |
{ |
while((i<=10)&&((DirectoryEntry[index].name[i] == item->searchstring[i]) || (item->searchstring[i]=='*') || item->searchstring[i]=='?')) |
{ |
i++; |
} |
} |
if((i==11) && (DirectoryEntry[index].attribute & item->attribute)) |
{ |
for(readpointer=0;readpointer<=10;readpointer++) |
{ |
if(DirectoryEntry[index].name[readpointer] != ' ') |
{ |
item->name[writepointer] = DirectoryEntry[index].name[readpointer]; // copy the name of the item found to the find_structure. |
writepointer++; |
} |
else if((readpointer==7) && (DirectoryEntry[index].attribute == _FILE)) // if the item found is a file |
{ |
if(DirectoryEntry[index].name[readpointer] != ' ') |
{ |
item->name[writepointer] = DirectoryEntry[index].name[readpointer]; // copy the name of the item found to the find_structure. |
writepointer++; |
} |
item->name[writepointer] = '.'; // then seperate the name and the extension by a '.' at index 8. |
writepointer++; |
} |
} |
item->startcluster = (u16)DirectoryEntry[index].startcluster; |
item->directory_index = ++index; |
item->cluster_pointer = file.cluster_pointer; |
retvalue = 1; |
} |
index++; |
} |
readpointer++; |
if(!retvalue) // file not found in this sector so take next sector. |
{ |
end_of_directory_not_reached = GetNextCluster(&file); |
} |
index = 0; |
} |
readpointer = fileindex; // start seperating the filename from the directory at the stored position. |
dircnt = 0; |
while((end_of_directory_not_reached) && (!retvalue)); |
return(retvalue); |
} |
while((writepointer<=10) && (fname[readpointer]!=0)) // the rootdirectoryentry is 8bytes for filename and 3bytes for fileattribute. |
{ // the filename in the rootdirectory is in the format "TEST TXT" without the dot. |
if(fname[readpointer]=='.') // seperating filename and attribute. |
//________________________________________________________________________________________________________________________________________ |
// Funtion: u8 findfirst(s8 *fname, Find *) |
// |
// Description: finds the first item (file or directory) within common working directory (cwd). Wildcards '*' or '?' will be considered. |
// |
// Returnvalue: If an item was found this function returns '1' else '0'. |
//________________________________________________________________________________________________________________________________________ |
u8 findfirst_(s8 *fname, Find *item, u8 attribute) |
{ |
u8 retvalue = 0; |
u8 i = 0; |
for(i=0;i<=11;i++) |
{ |
item->searchstring[i] = '*'; // initialise the searchstring with wildcards. |
item->name[i] = 0; |
} |
SeperateFileName(fname,item->searchstring); |
item->cluster_pointer = CWD; // findfirst_ starts at the beginning of the cwd. |
item->directory_index = 0; |
item->attribute = attribute; |
retvalue = FindItem(item); |
return(retvalue); |
} |
//________________________________________________________________________________________________________________________________________ |
// Funtion: u8 findnext(Find *) |
// |
// Description: finds the first item (file or directory) within common working directory (cwd). Wildcards '*' or '?' will be considered. |
// |
// Returnvalue: If an item was found this function returns '1' else '0'. |
//________________________________________________________________________________________________________________________________________ |
u8 findnext_(Find *item) |
{ |
u8 retvalue = 0; |
u8 i = 0; |
for(i=0;i<=11;i++) // copy the name of the searched item to the findstructure. |
{ |
item->name[i] = 0; |
} |
retvalue = FindItem(item); // search the item. |
return(retvalue); |
} |
//________________________________________________________________________________________________________________________________________ |
// Funtion: u8 fdelete(s8 *fname) |
// |
// Description: Deletes the file specified by fname. |
// |
// Returnvalue: |
//________________________________________________________________________________________________________________________________________ |
u8 fdelete_(s8 *fname) |
{ |
u8 retvalue = 0; |
Find item; |
retvalue = findfirst_(fname,&item, _FILE); // look for the item to be deleted. |
if(retvalue); // item found? |
{ |
DeleteClusterChain(item.startcluster); // delete all fatentries of the item. |
DeleteDirectoryEntry(&item); // free the directoryentry. |
do |
{ |
readpointer++; |
writepointer=8; |
retvalue = findnext_(&item); |
if(retvalue) |
{ |
DeleteClusterChain(item.startcluster); // delete all fatentries of the item. |
DeleteDirectoryEntry(&item); // free the directoryentry. |
} |
} |
else |
while(retvalue); |
} |
return(retvalue); |
} |
//________________________________________________________________________________________________________________________________________ |
// Funtion: u8 rmdir(s8 *fname) |
// |
// Description: Deletes the directory specified by dname. |
// |
// Returnvalue: |
//________________________________________________________________________________________________________________________________________ |
u8 rmdir_(s8 *dname) |
{ |
u8 retvalue = 0; |
Find item; |
retvalue = findfirst_(dname,&item, _DIRECTORY); // look for the item to be deleted. |
if(retvalue); // item found? |
{ |
DeleteClusterChain(item.startcluster); // delete all fatentries of the item. |
DeleteDirectoryEntry(&item); // free the directoryentry. |
do |
{ |
if((fname[readpointer]>96) && (fname[readpointer]<123)) |
retvalue = findnext_(&item); |
if(retvalue) |
{ |
name[writepointer]=(fname[readpointer] - 32); // all characters must be upper case. |
DeleteClusterChain(item.startcluster); // delete all fatentries of the item. |
DeleteDirectoryEntry(&item); // free the directoryentry. |
} |
else |
{ |
name[writepointer]=fname[readpointer]; |
} |
readpointer++; |
writepointer++; |
} |
} |
while(retvalue); |
} |
return(retvalue); |
} |
//________________________________________________________________________________________________________________________________________ |
// Funtion: u16 feof_(File *file) |
// |
// Description: This function checks wether the end of the file has been reached. |
// |
// Returnvalue: 0 if the end of the file was not reached otherwise 1. |
//________________________________________________________________________________________________________________________________________ |
u16 feof_(File *file) |
{ |
if(((file->fileposition)+1) < (file->filesize)) |
{ |
return(0); |
} |
else |
{ |
return(1); |
} |
} |
/trunk/fat16.h |
---|
2,17 → 2,23 |
#define __fat16_h |
//________________________________________________________________________________________________________________________________________ |
// |
// Definitions |
// Userspecific definitions |
// |
//________________________________________________________________________________________________________________________________________ |
//#define __USE_TIME_DATE_ATTRIBUTE |
#define __MAX_FILES_USED 2 // The number of files that can accessed simultaneously. |
#define __MAX_FILES_USED 1 // The number of files that can be opened simultaneously. |
#define MBR_SECTOR 0 // the masterboot record is located in sector 0. |
#define _UNUSED 1 // Bits used in the attribute of an directory entry. |
//________________________________________________________________________________________________________________________________________ |
// |
// Structure of a filepointer |
// |
//________________________________________________________________________________________________________________________________________ |
#define _UNUSED 1 // Bits used in the attribute of an directory entry. |
#define _USED 2 |
#define _ARCHIVE 2 |
#define _READ_ONLY 4 |
21,47 → 27,79 |
#define _FILE 32 |
typedef struct afile |
{ |
u32 start_cluster; // Sectorpointer to the first sector of the first datacluster of the file. |
u32 cluster_pointer; // Pointer to the cluster which is edited at the moment. |
u8 sector_index; // The sector which is edited at the moment (cluster_pointer + sector_index). |
u16 byte_index; // The bytelocation within the current sector (cluster_pointer + sector_index + byte_index). |
u8 mode; // mode of fileoperation (read,write) |
u32 filesize; // the size of the opend file in bytes. |
u32 fileposition; // pointer to a character within the file 0 < fileposition < filesize |
u32 sector_in_buffer; // the last sector read, wich is still in the sectorbuffer. |
u32 directory_root_sector; // pointer to the root of the |
u32 directory_sector; // the sectorposition where the directoryentry has been made. |
u8 directory_index; // the index to the directoryentry within the specified sector. |
u8 attribute; // the attribute of the file opened. |
u8 buffer[512]; // Buffer for read and write operation from or to the mmc. |
u8 state; // state of the filepointer (used/unused/...) |
} File; |
typedef enum |
{ |
NOT_INITIALIZED, |
INITIALIZED |
}Fat16_VolumeState_t; |
//________________________________________________________________________________________________________________________________________ |
// |
// Structure of a filepointer |
// Structure of an item to find within the cwd |
// |
//________________________________________________________________________________________________________________________________________ |
typedef struct afile |
struct volume |
{ |
u32 start_cluster; // Sectorpointer to the first sector of the first datacluster of the file. |
u32 cluster_pointer; // Pointer to the cluster which is edited at the moment. |
u8 sector_index; // The sector which is edited at the moment (cluster_pointer + sector_index). |
u16 byte_index; // The bytelocation within the current sector (cluster_pointer + sector_index + byte_index). |
u8 mode; // mode of fileoperation (read,write) |
u32 filesize; // the size of the opend file in bytes. |
u32 fileposition; // pointer to a character within the file 0 < fileposition < filesize |
u32 sector_in_buffer; // the last sector read, wich is still in the sectorbuffer. |
u32 directory_sector; // the sectorposition where the directoryentry has been made. |
u8 directory_index; // the index to the directoryentry within the specified sector. |
u8 attribute; // the attribute of the file opened. |
u8 buffer[512]; // Buffer for read and write operation from or to the mmc. |
u8 state; // state of the filepointer (used/unused/...) |
} File; |
Fat16_VolumeState_t state; // state of the volume |
} str_Volume; |
//________________________________________________________________________________________________________________________________________ |
// |
// Structure of an directoryentry |
// Structure of an item to find within the cwd |
// |
//________________________________________________________________________________________________________________________________________ |
typedef struct find |
{ |
s8 name[12]; // filename + extension or directoryname of the item found within the cwd. |
s8 searchstring[13]; |
u32 cluster_pointer; // Sectorpointer to the sector of the item searched within the cwd. |
u16 startcluster; // pointer to the first datacluster of the item found in the cwd. |
u32 filesize; // the size of the opend file in bytes. |
u32 directory_sector; // the sector within the actual cluster where the directoryentry was found. |
u8 directory_index; // the index to the directoryentry within the specified sector. |
u8 attribute; // the attribute of the file opened. |
} Find; |
//________________________________________________________________________________________________________________________________________ |
// |
// Directoryentries |
// |
//________________________________________________________________________________________________________________________________________ |
struct DirEntry |
{ |
u8 name[8]; // 8 bytes name. |
u8 extension[3]; // 3 bytes extension. |
u8 attribute; // attribute of the directory entry (unused,archive,read-only,system,directory,volume) |
u8 reserved[10]; // reserved bytes within the directory entry. |
u8 name[8]; // 8 bytes name. |
u8 extension[3]; // 3 bytes extension. |
u8 attribute; // attribute of the directory entry (unused,archive,read-only,system,directory,volume) |
u8 reserved[10]; // reserved bytes within the directory entry. |
u16 time; // time and |
u16 date; // date of last write acces to the file or directory. |
u16 startcluster; // first cluster of the file or directory. |
u32 size; // size of the file or directory in bytes. |
}; |
u32 size; // size of the file or directory in bytes. |
} __attribute__((packed)); |
//________________________________________________________________________________________________________________________________________ |
// |
72,7 → 110,7 |
struct FatEntry |
{ |
u16 next_cluster; // the next cluster of the file. |
}; |
} __attribute__((packed)); |
80,10 → 118,30 |
//________________________________________________________________________________________________________________________________________ |
// |
// Structure of an partitionentry |
// Partitions |
// |
//________________________________________________________________________________________________________________________________________ |
#define _EMPTY 0x00 |
#define _FAT12 0x01 |
#define _FAT16_ST_32_MB 0x04 |
#define _EXTENDED 0x05 |
#define _FAT16_LT_32_MB 0x06 |
#define _HPFS 0x07 |
#define _FAT32 0x0B |
#define _FAT32_BIOS_Extension 0x0C |
#define _FAT16_32_MB_BIOS_Extension 0x0E |
#define _EXTENDED_BIOS_Extension 0x0F |
#define _EISA 0x12 |
#define _DYNAMIC 0x42 |
#define _Linux_Swap 0x82 |
#define _Linux_Native 0x83 |
#define _Linux_LVM 0x8E |
#define _FreeBSD 0xA5 |
#define _OpenBSD 0xA6 |
#define _NetBSD 0xA9 |
struct PartitionEntry |
{ |
u8 PartitionState; |
124,6 → 182,8 |
// |
//________________________________________________________________________________________________________________________________________ |
#define _MBR_SECTOR 0 // The MasterBootRecord is located in sector 0 |
struct MBR_Entry |
{ |
u8 ExecutableCode[446]; |
144,19 → 204,26 |
//________________________________________________________________________________________________________________________________________ |
extern u8 InitFat16(void); |
extern File * fopen_(u8 *fname,s8 mode); |
extern File * fopen_(s8 *fname,s8 mode); |
extern s16 fflush_(File *file); |
extern void fclose_(File *file); |
extern u32 fread_(void *buffer, u32 size, u32 count, File *file); |
extern u32 fwrite_(void *buffer, u32 size, u32 count, File *file); |
extern s16 fseek_(File *file, s32 offset, s16 origin); |
extern s16 fgetchar_(File *file); |
extern s16 fgetchar_(File *file); |
extern u8 fputchar_(File *file,s8 c); |
extern u8 fputs_(File *file,s8 *string); |
extern s8 * fgets_(s8 *s, s16 count, File *file); |
extern s16 frename_(s8 *oldname, s8 *newname); |
extern u8 fexist_(u8*fname); |
extern u8 fexist_(s8 *fname); |
extern u8 mkdir_(s8 *fname); |
extern u8 chdir_(s8 *fname); |
extern u8 findfirst_(s8 *fname, Find *item, u8 attribute); |
extern u8 findnext_(Find *item); |
extern u16 feof_(File *); |
//________________________________________________________________________________________________________________________________________ |
// |
// Functions needed internaly for the fat16 implementation |
163,17 → 230,21 |
// |
//________________________________________________________________________________________________________________________________________ |
extern u8 CreateDirectoryEntry(u8*fname, u16 cluster, File *file,u8 attrib); |
extern u8 SeekFileInDirectory(s8*fname, File *file); |
extern u8 CreateFileInDirectory(s8*fname, File *file); |
extern u16 FindNextFreeCluster(File *file); |
extern u8 SeekDirectoryEntry(u8*fname, File *file); |
extern void SeperateFileName(u8*fname, u8*name); |
extern u8 ScanSubDirectories(u8*fname, File *file); |
extern void SeperateFileName(s8*fname, s8*name); |
extern u8 ScanSubDirectories(s8*fname, File *file); |
extern u16 GetNextCluster(File *file); |
extern u8 AppendCluster(File *file); |
extern u16 GetFatClusterOffset(File *file); |
extern u16 GetFatSectorIndex(File *file); |
extern File * ReserveFilePointer(void); |
extern u16 SeekSubDirectory(s8 *fname); |
extern u8 CreateSubDirectory_(s8 *fname); |
extern u8 FindItem(Find *); |
extern void FreeFilePointer(File *file); |
//________________________________________________________________________________________________________________________________________ |
// |
// Vaiables needed internaly for the fat16 implementation |
181,9 → 252,10 |
//________________________________________________________________________________________________________________________________________ |
extern u8 SectorsPerCluster; |
extern u8 SectorsPerCluster; |
extern u32 CWD; |
extern struct time rtctime; |
#endif |
/trunk/interrupt.c |
---|
304,6 → 304,16 |
*******************************************************************************/ |
void EXTIT1_IRQHandler(void) |
{ |
VIC_ITCmd(EXTIT1_ITLine, DISABLE); |
if(WIU_GetITStatus(WIU_Line11) != RESET) |
{ |
BeepTime = 100; |
InitFat16(); // initialize sd-card file system. |
WIU_ClearFlag(WIU_Line1); |
WIU_ClearITPendingBit(WIU_Line11); |
} |
VIC_ITCmd(EXTIT1_ITLine, ENABLE); |
} |
/******************************************************************************* |
* Function Name : EXTIT2_IRQHandler |
/trunk/kml.c |
---|
0,0 → 1,357 |
/*#######################################################################################*/ |
/* !!! THIS IS NOT FREE SOFTWARE !!! */ |
/*#######################################################################################*/ |
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
// + Copyright (c) 2008 Ingo Busker, Holger Buss |
// + Nur für den privaten Gebrauch |
// + FOR NON COMMERCIAL USE ONLY |
// + www.MikroKopter.com |
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
// + Es gilt für das gesamte Projekt (Hardware, Software, Binärfiles, Sourcecode und Dokumentation), |
// + dass eine Nutzung (auch auszugsweise) nur für den privaten (nicht-kommerziellen) Gebrauch zulässig ist. |
// + Sollten direkte oder indirekte kommerzielle Absichten verfolgt werden, ist mit uns (info@mikrokopter.de) Kontakt |
// + bzgl. der Nutzungsbedingungen aufzunehmen. |
// + Eine kommerzielle Nutzung ist z.B.Verkauf von MikroKoptern, Bestückung und Verkauf von Platinen oder Bausätzen, |
// + Verkauf von Luftbildaufnahmen, usw. |
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
// + Werden Teile des Quellcodes (mit oder ohne Modifikation) weiterverwendet oder veröffentlicht, |
// + unterliegen sie auch diesen Nutzungsbedingungen und diese Nutzungsbedingungen incl. Copyright müssen dann beiliegen |
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
// + Sollte die Software (auch auszugesweise) oder sonstige Informationen des MikroKopter-Projekts |
// + auf anderen Webseiten oder sonstigen Medien veröffentlicht werden, muss unsere Webseite "http://www.mikrokopter.de" |
// + eindeutig als Ursprung verlinkt werden |
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
// + Keine Gewähr auf Fehlerfreiheit, Vollständigkeit oder Funktion |
// + Benutzung auf eigene Gefahr |
// + Wir übernehmen keinerlei Haftung für direkte oder indirekte Personen- oder Sachschäden |
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
// + Die PORTIERUNG der Software (oder Teile davon) auf andere Systeme (ausser der Hardware von www.mikrokopter.de) ist nur |
// + mit unserer Zustimmung zulässig |
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
// + Die Funktion printf_P() unterliegt ihrer eigenen Lizenz und ist hiervon nicht betroffen |
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
// + Redistributions of source code (with or without modifications) must retain the above copyright notice, |
// + this list of conditions and the following disclaimer. |
// + * Neither the name of the copyright holders nor the names of contributors may be used to endorse or promote products derived |
// + from this software without specific prior written permission. |
// + * The use of this project (hardware, software, binary files, sources and documentation) is only permitted |
// + for non-commercial use (directly or indirectly) |
// + Commercial use (for excample: selling of MikroKopters, selling of PCBs, assembly, ...) is only permitted |
// + with our written permission |
// + * If sources or documentations are redistributet on other webpages, out webpage (http://www.MikroKopter.de) must be |
// + clearly linked as origin |
// + * PORTING this software (or part of it) to systems (other than hardware from www.mikrokopter.de) is NOT allowed |
// |
// + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
// + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
// + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
// + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
// + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
// + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
// + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
// + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
// + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
// + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
// + POSSIBILITY OF SUCH DAMAGE. |
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
#include <stdio.h> |
#include "main.h" |
#include "kml.h" |
#include "kml_header.h" |
#include "fat16.h" |
//________________________________________________________________________________________________________________________________________ |
// Module name: kml.c |
// Compiler used: avr-gcc 3.4.5 |
// Last Modifikation: 17.03.2008 |
// Version: 1.02 |
// Authors: Stephan Busker |
// Description: Source files to write gps-coordinates to a file in the kml (keyhole markup language) fileformat |
// Copyright (C) 2007 Stephan Busker |
//........................................................................................................................................ |
// Functions: extern u8 KML_LoggGPSCoordinates(struct str_gps_nav_data , KML_Document_t *); // intializes the kml-document with standard filename and adds points to the file |
// extern u8 KML_DocumentInit(KML_Document_t *doc) // initializes the kml-document to resetvalues. |
// extern u8 KML_DocumentOpen(s8 *, KML_Document_t *); // opens a new kml document. A filename can be specified. |
// extern u8 KML_DocumentClose(KML_Document_t *doc); // closes an open document |
// extern u8 KML_PlaceMarkOpen(s8 *name, KML_Document_t *); // opens a new placemark within the specified document |
// extern u8 KML_PlaceMarkClose( KML_Document_t *); // Closes the placemark |
// extern u8 KML_LineStringBegin(KML_Document_t *); // begins a new line within the actual placemark |
// extern u8 KML_LineStringEnd(KML_Document_t *doc); // ends the actual linestring |
// extern u8 KML_LineStringAddPoint(struct str_gps_nav_data, KML_Document_t *); // adds a new point (gps-coordinates) to the actual linestring |
//........................................................................................................................................ |
// ext. functions: |
// |
//........................................................................................................................................ |
// |
// URL: www.Mikro-Control.de |
// mailto: stephan.busker@mikro-control.de |
//________________________________________________________________________________________________________________________________________ |
//________________________________________________________________________________________________________________________________________ |
// Funtion: KML_DocumentInit(KML_Document_t *) |
// |
// Description: This function initializes the kml-document for further use. |
// |
// |
// Returnvalue: '1' if document was initialized |
//________________________________________________________________________________________________________________________________________ |
u8 KML_DocumentInit(KML_Document_t *doc) |
{ |
doc->name[0] = 0; // name of the document |
doc->state = DOC_CLOSED; // state of the kml-document |
doc->file = NULL; |
doc->place.name[0]=0; |
doc->place.description[0]=0; |
return(1); |
} |
//________________________________________________________________________________________________________________________________________ |
// Funtion: KML_Document_Open(void); |
// |
// Description: This function opens a new KML- document with the specified name and creates the document header within the file. |
// |
// |
// Returnvalue: '1' if the KML- file could be created. |
//________________________________________________________________________________________________________________________________________ |
u8 KML_DocumentOpen(s8 *name, KML_Document_t *doc) |
{ |
u8 retvalue = 0; |
KML_DocumentInit(doc); // intialize the document with resetvalues |
doc->file = fopen_(name,'a'); // open a new file with the specified filename on the memorycard. |
if(doc->file != NULL) // could the file be opened? |
{ |
retvalue = 1; // the document could be created on the drive. |
doc->state = DOC_OPENED; // change document state to opened. At next a placemark has to be opened. |
fwrite_(KML_DOCUMENT_HEADER, sizeof(KML_DOCUMENT_HEADER)-1,1,doc->file); // write the KML- footer to the document. |
} |
return(retvalue); |
} |
//________________________________________________________________________________________________________________________________________ |
// Funtion: DocumentClose(KML_Document_t *doc); |
// |
// Description: This function closes the document specified by doc. |
// |
// |
// Returnvalue: none |
//________________________________________________________________________________________________________________________________________ |
u8 KML_DocumentClose(KML_Document_t *doc) |
{ |
u8 retvalue = 0; |
while(doc->state != DOC_CLOSED) // close linestring, placemark and document before closing the file on the memorycard |
{ |
switch(doc->state) |
{ |
case DOC_LINESTRING_OPENED: |
KML_LineStringEnd(doc); // write terminating tag to end linestring. |
doc->state = DOC_PLACEMARK_OPENED; |
break; |
case DOC_PLACEMARK_OPENED: // write terminating tag to close placemark. |
KML_PlaceMarkClose(doc); |
doc->state = DOC_OPENED; |
break; |
case DOC_OPENED: // close the file on the memorycard |
if(doc->file != NULL) |
{ |
fwrite_(KML_DOCUMENT_FOOTER, sizeof(KML_DOCUMENT_FOOTER)-1,1,doc->file); // write the KML- footer to the document. |
fclose_(doc->file); |
retvalue = 1; |
} |
doc->state = DOC_CLOSED; |
break; |
} |
}; |
return(retvalue); |
} |
//________________________________________________________________________________________________________________________________________ |
// Funtion: u8 PlaceMarkOpen(s8 *name, File *file); |
// |
// Description: This function adds a placemark to the document. |
// |
// |
// Returnvalue: none |
//________________________________________________________________________________________________________________________________________ |
u8 KML_PlaceMarkOpen(s8 *name, KML_Document_t *doc) |
{ |
u8 retvalue = 0; |
if(doc->file != NULL) |
{ |
doc->state = DOC_PLACEMARK_OPENED; |
retvalue = 1; |
fwrite_(KML_PLACEMARK_HEADER, sizeof(KML_PLACEMARK_HEADER)-1,1,doc->file); |
} |
return(retvalue); |
} |
//________________________________________________________________________________________________________________________________________ |
// Funtion: u8 PlaceMarkClose(KML_PlaceMark_t *place, File *file); |
// |
// Description: This function ends the placemark opened before. |
// |
// |
// Returnvalue: none |
//________________________________________________________________________________________________________________________________________ |
u8 KML_PlaceMarkClose(KML_Document_t *doc) |
{ |
u8 retvalue = 0; // close the Placemark-tag of the corosponding document. |
if(doc->state == DOC_PLACEMARK_OPENED) |
{ |
if(doc->file != NULL) |
{ |
doc->state =DOC_OPENED; |
fwrite_(KML_PLACEMARK_FOOTER, sizeof(KML_PLACEMARK_FOOTER)-1,1,doc->file); |
retvalue = 1; |
} |
} |
return(retvalue); |
} |
//________________________________________________________________________________________________________________________________________ |
// Funtion: u8 LineStringBegin(KML_Document_t *doc); |
// |
// Description: This function ends the placemark opened before. |
// |
// |
// Returnvalue: none |
//________________________________________________________________________________________________________________________________________ |
u8 KML_LineStringBegin(KML_Document_t *doc) |
{ |
u8 retvalue = 0; |
if(doc->file != NULL) |
{ |
doc->state = DOC_LINESTRING_OPENED; |
fwrite_(KML_LINESTRING_HEADER, sizeof(KML_LINESTRING_HEADER)-1,1,doc->file); |
retvalue = 1; |
} |
return(retvalue); |
} |
//________________________________________________________________________________________________________________________________________ |
// Funtion: u8 LineStringEnd(KML_Document_t *doc) |
// |
// Description: This function ends the placemark opened before. |
// |
// |
// Returnvalue: none |
//________________________________________________________________________________________________________________________________________ |
u8 KML_LineStringEnd(KML_Document_t *doc) |
{ |
u8 retvalue = 0; |
if(doc->state == DOC_LINESTRING_OPENED); |
if(doc->file != NULL) |
{ |
doc->state = DOC_PLACEMARK_OPENED; |
fwrite_(KML_LINESTRING_FOOTER, sizeof(KML_LINESTRING_FOOTER)-1,1,doc->file); |
retvalue = 1; |
} |
return(retvalue); |
} |
//________________________________________________________________________________________________________________________________________ |
// Funtion: u8 LineStringAddPoint(struct str_GPSPosition, KML_Document_t *doc) |
// |
// Description: This function adds a point to the specified document. |
// |
// |
// Returnvalue: none |
//________________________________________________________________________________________________________________________________________ |
u8 KML_LineStringAddPoint(struct str_gps_nav_data gps_data ,KML_Document_t *doc) |
{ |
u8 retvalue = 0; |
s8 string[50]; |
if(doc->state == DOC_LINESTRING_OPENED) |
{ |
if(doc->file != NULL) |
{ |
sprintf(string,"\r\n%d.%d,%d.%d,%d.0",(gps_data.Longitude/10000000),(gps_data.Longitude%10000000),(gps_data.Latitude/10000000),(gps_data.Latitude%10000000),0); |
fputs_(doc->file,string); |
retvalue = 1; |
} |
} |
return(retvalue); |
} |
//________________________________________________________________________________________________________________________________________ |
// Funtion: u8 KML_LoggGPSCoordinates(struct str_gps_nav_data, KML_Document_t *) |
// |
// Description: This function opens adds gpscoordinates to an KML-Document. The document will be opened, if not already done |
// |
// |
// Returnvalue: none |
//________________________________________________________________________________________________________________________________________ |
u8 KML_LoggGPSCoordinates(struct str_gps_nav_data gps_data, KML_Document_t *doc) |
{ |
while(doc->state != DOC_LINESTRING_OPENED) // automatic create document with default filename on the card. |
{ |
switch(doc->state) |
{ |
case DOC_CLOSED: // document hasn't been opened yet therefore it will be initialized automatically |
KML_DocumentInit(doc); // initialize the document to default values |
if(KML_DocumentOpen("default.kml",doc)) // open the kml-document with a standardname. |
{ |
doc->state = DOC_OPENED; |
} |
break; |
case DOC_OPENED: // if a document has been opened before but no placemark exists: |
if(KML_PlaceMarkOpen("MIKROKOPTER",doc)) |
{ |
doc->state = DOC_PLACEMARK_OPENED; // add a placemark to the document. |
} |
break; |
case DOC_PLACEMARK_OPENED: // add linestring to the placemark |
if(KML_LineStringBegin(doc)) |
{ |
doc->state = DOC_LINESTRING_OPENED; |
} |
break; |
} |
}; |
if(doc->state == DOC_LINESTRING_OPENED) // if the document was opened add coordinates to the document. |
{ |
KML_LineStringAddPoint(gps_data , doc); |
} |
} |
/trunk/kml.h |
---|
0,0 → 1,49 |
#ifndef _KML_H |
#define _KML_H |
#include "fat16.h" |
// possible state of an kml-document |
typedef enum |
{ |
DOC_CLOSED, |
DOC_OPENED, |
DOC_PLACEMARK_OPENED, |
DOC_LINESTRING_OPENED, |
DOC_END |
}KML_DocState_t; |
// structure of an kml-placemarkt |
typedef struct kml_place |
{ |
s8 name[10]; // the name of the placemark |
s8 description[40]; // some text as a description to the placemark |
} KML_PlaceMark_t; |
// structure of an kml-document |
typedef struct kml_doc |
{ |
u8 name[40]; // name of the document |
KML_DocState_t state; // state of the kml-document |
File *file; // filepointer to the file where the data should be saved. |
KML_PlaceMark_t place; |
} KML_Document_t; |
#endif |
extern u8 KML_LoggGPSCoordinates(struct str_gps_nav_data , KML_Document_t *); |
extern u8 KML_DocumentInit(KML_Document_t *); // Init the new kml-document |
extern u8 KML_DocumentOpen(s8 *, KML_Document_t *); // opens a new kml-document. a new file is created on the sd-memorycard |
extern u8 KML_DocumentClose(KML_Document_t *doc); // closes the specified document saving remaining data to the file. |
extern u8 KML_PlaceMarkOpen(s8 *name, KML_Document_t *doc); // opens a new placemark within the open kml-document |
extern u8 KML_PlaceMarkClose(KML_Document_t *doc); // closes the actual placemark |
extern u8 KML_LineStringBegin(KML_Document_t *doc); // begins a new linestring within the actual placemark |
extern u8 KML_LineStringEnd(KML_Document_t *doc); // close the actual linestring within the actual placemark |
extern u8 KML_LineStringAddPoint(struct str_gps_nav_data, KML_Document_t *); // adds a point from the gps (longitude, altitude, height) to the linestring |
/trunk/kml_header.h |
---|
0,0 → 1,107 |
//________________________________________________________________________________________________________________________________________ |
// |
// Definition of KML header and footer elements for documents, placemarks and linestrings |
// |
//________________________________________________________________________________________________________________________________________ |
const s8 KML_DOCUMENT_HEADER[] = |
{ |
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n" |
"<kml xmlns=\"http://earth.google.com/kml/2.2\">\r\n" |
"<Document>\r\n" |
" <name>Mikrokopter GPS logging</name>\r\n" |
" <StyleMap id=\"msn_ylw-pushpin\">\r\n" |
" <Pair>\r\n" |
" <key>normal</key>\r\n" |
" <styleUrl>#sn_ylw-pushpin</styleUrl>\r\n" |
" </Pair>\r\n" |
" <Pair>\r\n" |
" <key>highlight</key>\r\n" |
" <styleUrl>#sh_ylw-pushpin</styleUrl>\r\n" |
" </Pair>\r\n" |
" </StyleMap>\r\n" |
" <Style id=\"sn_ylw-pushpin\">\r\n" |
" <IconStyle>\r\n" |
" <scale>1.1</scale>\r\n" |
" <Icon>\r\n" |
" <href>http://maps.google.com/mapfiles/kml/pushpin/ylw-pushpin.png</href>\r\n" |
" </Icon>\r\n" |
" <hotSpot x=\"20\" y=\"2\" xunits=\"pixels\" yunits=\"pixels\"/>\r\n" |
" </IconStyle>\r\n" |
" </Style>\r\n" |
" <Style id=\"sh_ylw-pushpin\">\r\n" |
" <IconStyle>\r\n" |
" <scale>1.3</scale>\r\n" |
" <Icon>\r\n" |
" <href>http://maps.google.com/mapfiles/kml/pushpin/ylw-pushpin.png</href>\r\n" |
" </Icon>\r\n" |
" <hotSpot x=\"20\" y=\"2\" xunits=\"pixels\" yunits=\"pixels\"/>\r\n" |
" </IconStyle>\r\n" |
" </Style>\r\n" |
}; |
//________________________________________________________________________________________________________________________________________ |
// |
// footer of an KML- file. |
// |
//________________________________________________________________________________________________________________________________________ |
const s8 KML_DOCUMENT_FOOTER[] = |
{ |
" </Document>\r\n" |
"</kml>\r\n" |
}; |
//________________________________________________________________________________________________________________________________________ |
// |
// Header of an placemark |
// |
//________________________________________________________________________________________________________________________________________ |
const s8 KML_PLACEMARK_HEADER[] = |
{" <Placemark>\r\n" |
" <name>flight</name>\r\n" |
" <styleUrl>#msn_ylw-pushpin</styleUrl>\r\n"}; |
//________________________________________________________________________________________________________________________________________ |
// |
// Footer of an placemark |
// |
//________________________________________________________________________________________________________________________________________ |
const s8 KML_PLACEMARK_FOOTER[] = { |
" </Placemark>\r\n"}; |
//________________________________________________________________________________________________________________________________________ |
// |
// Footer of an placemark |
// |
//________________________________________________________________________________________________________________________________________ |
const s8 KML_LINESTRING_HEADER[] = { |
" <LineString>\r\n" |
" <extrude>1</extrude>\r\n" |
" <tessellate>1</tessellate>\r\n" |
" <altitudeMode>relativeToGround</altitudeMode>\r\n" |
" <coordinates>\r\n" |
}; |
//________________________________________________________________________________________________________________________________________ |
// |
// Footer of an linestring |
// |
//________________________________________________________________________________________________________________________________________ |
const s8 KML_LINESTRING_FOOTER[] = { |
"\r\n </coordinates>" |
"\r\n </LineString>\r\n" |
}; |
/trunk/main.c |
---|
58,10 → 58,12 |
const unsigned long _Main_Crystal = 25000; |
#include "main.h" |
#include "kml.h" |
u32 TimerCompassUpdate; |
u32 TimerI2CReadDelay; |
u32 TimerDebugDataDelay; |
u32 KmlAddPointDelay; |
u8 BeepTime; |
void Init_Undef(void); |
99,6 → 101,7 |
GPIO_InitStructure.GPIO_Alternate = GPIO_OutputAlt1 ; |
GPIO_Init(GPIO5, &GPIO_InitStructure); |
//SD_SWITCH |
GPIO_InitStructure.GPIO_Direction = GPIO_PinInput; |
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; |
GPIO_InitStructure.GPIO_Type = GPIO_Type_PushPull; |
105,13 → 108,12 |
GPIO_InitStructure.GPIO_Alternate = GPIO_InputAlt1; |
GPIO_Init(GPIO5, &GPIO_InitStructure); |
} |
// |
void OutputStartupData(void) |
{ |
char text[20]; |
char tex[20]; |
SerialPutString("\n\r--------------\n\r"); |
sprintf(text,"NaviCtrl V%d.%d\n\r", VersionInfo.Hauptversion, VersionInfo.Nebenversion); SerialPutString(text); |
124,6 → 126,19 |
{ |
static u8 oldCompassCalState = 0; |
static u8 kml_state = 0; |
u8 kml_cnt = 0; |
KML_Document_t mydocument; |
File *file1; |
u8 str[80]; |
KML_DocumentInit(&mydocument); // Initialise the new kml-document for further use. |
// SCU_MCLKSourceConfig(SCU_MCLK_OSC); |
// SCU_PCLKDivisorConfig(SCU_PCLK_Div2); |
// SCU_MCLKSourceConfig(SCU_MCLK_PLL); |
178,14 → 193,18 |
TimerCompassUpdate = SetDelay(5); |
TimerI2CReadDelay = SetDelay(5); |
/* |
KmlAddPointDelay = SetDelay(250); |
SerialPutString("\r\n---------------------------------------------"); |
// ReadSetting(1); |
SerialPutString("\r\n---------------------------------------------\r\n\r\n"); |
InitFat16(); |
ReadSetting(1); |
*/ |
SerialPutString("Init done\n\r."); |
SerialPutString("--------------\n\n\r"); |
for (;;) |
{ |
if(NeuerDatensatzEmpfangen) |
238,7 → 257,51 |
TimerDebugDataDelay = SetDelay(500); |
} |
// ---------------------------------------------------- |
} |
// ----------- KML Timing ------------------------- |
if(CheckDelay(KmlAddPointDelay)) |
{ |
KmlAddPointDelay = SetDelay(500); |
switch(kml_state) |
{ |
case 0: |
if((GPS_Data.Flags & GPS_FIX) && (GPS_Data.Used_Sat >= GPS_SAT_MIN)) |
{ |
if(str_Volume.state == INITIALIZED) // has the volume and filesystem been initialized? |
{ |
if(KML_DocumentOpen("flight01.kml",&mydocument)) // create a new kml-document on the memorycard. |
{ |
SerialPutString("\r\nopening kml-file\r\nadding data"); |
kml_state = 1; |
} |
} |
else |
{ |
InitFat16(); |
} |
} |
break; // document.state will be changed to DOC_OPENED automatic. |
case 1: // linestring opened, so datapoint (gps_coordinates) can be added to the document. |
if(kml_cnt++ < 20) // add 10 datapoints to the document. |
{ |
KML_LoggGPSCoordinates(GPS_Data,&mydocument); |
} |
else // after the datapoints have been written to the document close the document. |
{ |
KML_DocumentClose(&mydocument); |
SerialPutString("\r\nfile closed"); |
kml_state = 2; |
} |
break; |
default: // all data has been written to card. open new document to add new data. |
} |
} |
} |
} |
/trunk/main.h |
---|
1,6 → 1,7 |
#include "91x_conf.h" |
#include "91x_lib.h" |
#include "91x_wiu.h" |
#include "uart.h" |
#include "ramfunc.h" |
#include "menu.h" |
16,9 → 17,7 |
#include "sdc.h" |
#include "ssc.h" |
#include "fat16.h" |
#include "usb.h" |
#include "string.h" |
#include "settings.h" |
/trunk/menu.c |
---|
78,6 → 78,7 |
void Menu(void) |
{ |
static u8 MaxMenue = 1,MenuePunkt=0; |
u8 text[20]; |
if(RemoteTasten & KEY1) { if(MenuePunkt) MenuePunkt--; else MenuePunkt = MaxMenue; LcdClear(); } |
if(RemoteTasten & KEY2) { MenuePunkt++; LcdClear(); } |
93,6 → 94,17 |
// if(RemoteTasten & KEY3) TestInt--; |
// if(RemoteTasten & KEY4) TestInt++; |
break; |
case 1: |
LCD_printfxy(0,0,"++ GPS-Logging ++"); |
sprintf(text, "latitude: %u",GPS_Data.Latitude); |
LCD_printfxy(0,1,text); |
sprintf(text, "longitude:%u",GPS_Data.Longitude); |
LCD_printfxy(0,2,text); |
sprintf(text, "used sat: %d",GPS_Data.Used_Sat); |
LCD_printfxy(0,3,text); |
break; |
default: MaxMenue = MenuePunkt - 1; |
MenuePunkt = 0; |
break; |
/trunk/sdc.c |
---|
54,30 → 54,37 |
// + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
// + POSSIBILITY OF SUCH DAMAGE. |
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
#include <stdio.h> |
#include <string.h> |
#include "91x_lib.h" |
#include "uart.h" |
#include "sdc.h" |
#include "ssc.h" |
#include "timer.h" |
#include "main.h" |
#include "crc16.h" |
//________________________________________________________________________________________________________________________________________ |
// Module name: mmc.c |
// Module name: sdc.c |
// Compiler used: avr-gcc 3.4.5 |
// Last Modifikation: 24.07.2007 |
// Version: 1.05 |
// Authors: Stephan Busker |
// Description: Source files for connecting to an sdcard using the SSC |
// Last Modifikation: 08.06.2008 |
// Version: 1.07 |
// Authors: Stephan Busker, Gregor Stobrawa |
// Description: Source files for connecting to an sd-card using the SSC |
// |
//........................................................................................................................................ |
// Functions: u8 SDC_init(void); |
// u8 SDC_PutCommand (u8 *CMD); |
// u8 SDC_PutSector(u32 addr,u8 *Buffer); |
// u8 SDC_GetSector(u32 addr,u8 *Buffer); |
// void SDC_GetBlock(u8 *CMD,u8 *Buffer,u16 Bytes); |
// Functions: SD_Result_t SDC_init(void); |
// u8 SDC_PutCommand (u8 *cmd); |
// SD_Result_t SDC_PutSector(u32 addr,u8 *Buffer); |
// SD_Result_t SDC_GetSector(u32 addr,u8 *Buffer); |
// |
////........................................................................................................................................ |
// ext. functions: extern void SSC_Init(void); |
// extern u8 SSC_GetChar (void); |
// extern u8 SSC_GetChar (void); |
// extern void SSC_PutChar (u8); |
// extern void SSC_Enable(void); |
// extern void SSC_Disable(void); |
// extern void SSC_ClearRxFifo(); |
//........................................................................................................................................ |
// |
// URL: www.Mikro-Control.de |
86,209 → 93,690 |
#define CMD_GO_IDLE_STATE 0x00 /* CMD00: response R1 */ |
#define CMD_SEND_OP_COND 0x01 /* CMD01: response R1 */ |
#define CMD_SEND_IF_COND 0x08 /* CMD08: response R7 */ |
#define CMD_SEND_CSD 0x09 /* CMD09: response R1 */ |
#define CMD_SEND_CID 0x0A /* CMD10: response R1 */ |
#define CMD_SEND_STATUS 0x0D /* CMD13: response R2 */ |
#define CMD_SET_BLOCKLEN 0x10 /* CMD16: arg0[31:0]: block length, response R1*/ |
#define CMD_READ_SINGLE_BLOCK 0x11 /* CMD17: arg0[31:0]: data address, response R1 */ |
#define CMD_WRITE_SINGLE_BLOCK 0x18 /* CMD24: arg0[31:0]: data address, response R1 */ |
#define CMD_APP_CMD 0x37 /* CMD55: response R1 */ |
#define CMD_READ_OCR 0x3A /* CMD58: response R3 */ |
#define CMD_CRC_ON_OFF 0x3B /* CMD59: arg0[31:1]: stuff bits, arg0[0:0]: crc option, response R1 */ |
#define ACMD_SEND_OP_COND 0x29 /* ACMD41: arg0[31]: stuff bits, arg0[30]: HCS, arg0[29:0] stuff bits*, response R1 */ |
#define R1_NO_ERR 0x00 |
#define R1_IDLE_STATE 0x01 |
#define R1_ERASE_RESET 0x02 |
#define R1_ILLEGAL_CMD 0x04 |
#define R1_COM_CRC_ERR 0x08 |
#define R1_ERASE_SEQUENCE_ERR 0x10 |
#define R1_ADDRESS_ERR 0x20 |
#define R1_PARAMETER_ERR 0x40 |
#define R1_BAD_RESPONSE 0x80 |
#define R2_NO_ERR 0x00 |
#define R2_CARD_LOCKED 0x01 |
#define R2_ERASE_WRITE_PROT_ERR 0x02 |
#define R2_UNKOWN_ERR 0x04 |
#define R2_CARD_CTRL_ERR 0x08 |
#define R2_CARD_ECC_ERR 0x10 |
#define R2_WRITE_PROT_ERR 0x20 |
#define R2_ERASE_PARAM_ERR 0x40 |
#define R2_OUT_OF_RANGE_ERR 0x80 |
#define DATA_START_TOKEN 0xFE |
#define DATA_RESPONSE_MASK 0x1F |
#define DATA_RESPONSE_OK 0x05 |
#define DATA_RESPONSE_CRC_ERR 0x0B |
#define DATA_RESPONSE_WRITE_ERR 0x1D |
typedef enum |
{ |
VER_UNKNOWN, |
VER_1X, |
VER_20 |
} SDVersion_t; |
typedef struct |
{ |
u8 Valid; |
SDVersion_t Version; // HW-Version |
u32 Capacity; // Memory capacity in bytes |
u8 CID[16]; // CID register |
u8 CSD[16]; // CSD register |
} __attribute__((packed)) SDCardInfo_t; |
volatile SDCardInfo_t SDCardInfo; |
//________________________________________________________________________________________________________________________________________ |
// Funtion: SDC_Init(void); |
// Function: CRC7(u8* cmd, u32 len); |
// |
// Description: This function initialises the SDCard to spi-mode. |
// Description: This function calculated the CRC7 checksum used in the last byte of a spi command frame. |
// |
// |
// Returnvalue: the function returns 0 if the initialisation was successfull otherwise the function returns an errorcode. |
// Returnvalue: the function returns the crc7 including bit 0 set to 1 |
//________________________________________________________________________________________________________________________________________ |
u8 SDC_Init(void) |
u8 CRC7(u8 * cmd, u32 len) |
{ |
u16 Timeout = 0; |
u8 CMD[] = {0x40,0x00,0x00,0x00,0x00,0x95}; |
u8 i, a; |
u8 crc, Data; |
u8 b; |
crc = 0; // init CRC buffer |
for (a = 0; a < len ;a++) // for every byte in the msg |
{ |
Data = cmd[a]; |
for (i=0;i<8;i++) // for every bit in the byte |
{ |
crc <<= 1; // shift crc |
if ((Data & 0x80)^(crc & 0x80)) crc ^=0x09; //xor |
Data <<= 1; // shift data for next bit |
} |
} |
crc = (crc<<1)|1; // set terminating bit to 1 |
return(crc); |
} |
SSC_Init(); // Initialise SSC to transmit data to the sdcard. |
SerialPutString("Init SD..."); |
// Delay_ms(10); |
u8 SDC_WaitForBusy() |
{ |
u8 rsp = 0; |
u16 timeout=0; |
for (b = 0;b<0x0f;b++) // sending 74Clocks brings the sdcard into spimode. |
SSC_ClearRxFifo(); |
SSC_Enable(); // enable chipselect. |
do |
{ |
SSC_PutChar(0xff); |
rsp = SSC_GetChar(); |
if(timeout++>500) break; |
}while(rsp != 0xFF); // wait while card is busy (data out low) |
return(rsp); |
} |
//________________________________________________________________________________________________________________________________________ |
// Function: SDC_SendCMDR1(u8 CmdNo, u32 arg); |
// |
// Description: This function send a command frame to the SD-Card in spi-mode. |
// |
// |
// Returnvalue: The function returns the first response byte like for R1 commands |
//________________________________________________________________________________________________________________________________________ |
u8 SDC_SendCMDR1(u8 CmdNo, u32 arg) |
{ |
u8 r1; |
u16 Timeout = 0; |
u16 a; |
u8 cmd[6]; |
SSC_ClearRxFifo(); // clear the rx fifo |
SSC_Enable(); // enable chipselect. |
SDC_WaitForBusy(); |
SSC_ClearRxFifo(); // clear the rx fifo |
SSC_GetChar(); // dummy to sync |
/* Send cmd10 (SEND_CID) */; |
cmd[0] = 0x40|CmdNo; // set command index |
cmd[1] = (arg & 0xFF000000)>>24; |
cmd[2] = (arg & 0x00FF0000)>>16; |
cmd[3] = (arg & 0x0000FF00)>>8; |
cmd[4] = (arg & 0x000000FF); |
cmd[5] = CRC7(cmd, 5); // update checksum |
for (a = 0;a < 6; a++) // send the command sequence to the sdcard (6 bytes) |
{ |
SSC_PutChar(cmd[a]); |
} |
SerialPutString("reset..."); |
while(SDC_PutCommand (CMD) !=1) // Sending CMD0 (Reset) to the sdcard. |
SSC_ClearRxFifo(); // clear the rx fifo to discard the bytes received during the transmission of the 6 command bytes |
do |
{ |
if (Timeout++ > 200) |
{ |
return(1); |
} |
} |
SerialPutString("ok."); |
Timeout = 0; |
CMD[0] = 0x41; |
CMD[5] = 0xFF; |
while( SDC_PutCommand (CMD) !=0) // Sending CMD1 to the sdcard. |
{ |
if (Timeout++ > 100) |
{ |
return(2); |
} |
} |
SSC_Disable(); // disable sdcard. |
return(0); |
r1 = SSC_GetChar(); // get byte from sd-card |
if (Timeout++ > 500) return(r1); |
}while(r1 == 0xFF); // wait for the response byte from sd-card. |
return(r1); |
} |
//________________________________________________________________________________________________________________________________________ |
// Function: SDC_SendACMDR1(u8 CmdNo, u32 arg); |
// |
// Description: This function send a application command frame to the SD-Card in spi-mode. |
// |
// |
// Returnvalue: The function returns the first response byte like for R1 commands |
//________________________________________________________________________________________________________________________________________ |
u8 SDC_SendACMDR1(u8 CmdNo, u32 arg) |
{ |
u8 r1 = 0xFF; |
r1 = SDC_SendCMDR1(CMD_APP_CMD, 0UL); |
if(r1 & R1_BAD_RESPONSE) return(r1); |
r1 = SDC_SendCMDR1(CmdNo, arg); |
return(r1); |
} |
//________________________________________________________________________________________________________________________________________ |
// Funtion: SDC_PutCommand(* CMD); |
// Function: SDC_GetData(u8 * cmd ,u8 *Buffer, u32 len); |
// |
// Description: This function initialises the SDCard to spi-mode. |
// Description: This function sneds cmd an reads a datablock of len from the sd-card |
// |
// |
// Returnvalue: the function returns 0 if the initialisation was successfull otherwise the function returns an errorcode. |
// Returnvalue: SD_Result_t |
//________________________________________________________________________________________________________________________________________ |
u8 SDC_PutCommand (u8 *CMD) |
SD_Result_t SDC_GetData(u8 CmdNo, u32 addr, u8 *Buffer, u32 len) |
{ |
u8 tmp = 0xff; |
u16 Timeout = 0; |
u16 a; |
SSC_ClearRxFifo(); |
SSC_Disable(); // disable chipselect |
SSC_PutChar(0xFF); // Send 8 Clocks to the sdcard while card is not selected. |
SSC_Enable(); // enable chipselect. |
u8 rsp; |
u16 timeout; |
u16 a, Crc16; |
SD_Result_t result = SD_ERROR_UNKNOWN; |
// if (*CMD == 0x41) Delay_ms(10); // if command is CMD0 generate a short delay. |
for (a = 0;a<0x06;a++) // send the command sequence to the sdcard (6 bytes) |
// send the command |
rsp = SDC_SendCMDR1(CmdNo, addr); |
if (rsp != R1_NO_ERR) |
{ |
SSC_PutChar(*CMD++); |
result = SD_ERROR_BAD_RESPONSE; |
goto end; |
} |
SSC_ClearRxFifo(); |
while (tmp == 0xff) // Wait for response from sdcard. |
do |
{ |
tmp = SSC_GetChar(); |
if (Timeout++ > 200) |
rsp = SSC_GetChar(); |
if((rsp & 0xF0) == 0x00) // data error token |
{ |
break; // or timeout. |
result = SD_ERROR_READ_DATA; |
goto end; |
} |
// if(timeout++>500) break; |
}while(rsp != DATA_START_TOKEN); |
// data start token received |
for (a = 0; a < len; a++) // read the block from the SSC |
{ |
Buffer[a] = SSC_GetChar(); |
} |
// Read two bytes CRC16-Data checksum |
Crc16 = SSC_GetChar(); // highbyte fisrt |
Crc16 = (Crc16<<8)|SSC_GetChar(); // lowbyte last |
// if(Crc16 != CRC16(Buffer, len)) result = SD_ERROR_CRC_DATA; |
/* else */result = SD_SUCCESS; |
end: |
//SSC_Disable(); // disable sdcard. |
if(result != SD_SUCCESS) |
{ |
sprintf(text,"Error %02X reading data from sd card (R1=%02X).\r\n", result, rsp); |
SerialPutString(text); |
} |
return(result); |
} |
return(tmp); |
//________________________________________________________________________________________________________________________________________ |
// Function: SDC_PrintCID(u8 * pCID); |
// |
// Description: This function prints the CIS register in a human readable format. |
// |
// |
// Returnvalue: the function returns nothing |
//________________________________________________________________________________________________________________________________________ |
void SDC_PrintCID(u8 * pCID) |
{ |
u8 text[50]; |
u8 pn[6]; |
u16 temp1, temp2; |
sprintf(text, "\r\nManufacturer ID: %i\r\n", pCID[0]); |
SerialPutString(text); |
memcpy(pn, &pCID[1], 2); |
pn[2] = '\0'; // terminate string |
sprintf(text, "Application ID: %s\r\n",pn); |
SerialPutString(text); |
memcpy(pn, &pCID[3], 5); |
pn[5] = '\0'; // terminate string |
sprintf(text, "Product Name: %s\r\n",pn); |
SerialPutString(text); |
sprintf(text, "Product Rev.: %i.%i\r\n",pCID[8]>>4, pCID[8]&0xF); |
SerialPutString(text); |
SerialPutString("Serial No.: "); |
for(temp1 = 0; temp1<4; temp1++) |
{ |
sprintf(text,"%02X", pCID[9+temp1]); |
SerialPutString(text); |
} |
SerialPutString("\r\n"); |
temp1 = pCID[14] & 0x0F; // month |
temp2 = ((pCID[14]>>4)|(pCID[13]<<4)) + 2000; // year |
sprintf(text, "Manufac. Date: %i/%i\r\n\r\n",temp1, temp2); |
SerialPutString(text); |
} |
//________________________________________________________________________________________________________________________________________ |
// Funtion: SDC_GetCID(u8 * pCID); |
// |
// Description: This function reads the CIS register form the sd card in spi mode. |
// |
// |
// Returnvalue: the function returns error state |
//________________________________________________________________________________________________________________________________________ |
SD_Result_t SDC_GetCID(u8 * pCID) |
{ |
return SDC_GetData(CMD_SEND_CID, 0UL, pCID, 16); |
} |
//________________________________________________________________________________________________________________________________________ |
// Funtion: SDC_GetCSD(u8 * pCSD); |
// |
// Description: This function reads the CSD register form the sd card in spi mode. |
// |
// |
// Returnvalue: the function returns error state |
//________________________________________________________________________________________________________________________________________ |
SD_Result_t SDC_GetCSD(u8 * pCSD) |
{ |
return SDC_GetData(CMD_SEND_CSD, 0UL, pCSD, 16); |
} |
//________________________________________________________________________________________________________________________________________ |
// Funtion: SDC_PutSector(void); |
// Funtion: SDC_Init(void); |
// |
// Description: This function writes one sector of data to the SSC |
// Description: This function initialises the SDCard to spi-mode. |
// |
// |
// Returnvalue: none |
// Returnvalue: the function returns 0 if the initialisation was successfull otherwise the function returns an errorcode. |
//________________________________________________________________________________________________________________________________________ |
u8 SDC_PutSector(u32 addr,u8 *Buffer) |
SD_Result_t SDC_Init(void) |
{ |
u8 tmp; |
u8 CMD[] = {0x58,0x00,0x00,0x00,0x00,0xFF}; |
u16 a; |
addr = addr << 9; // convert sectoradress to byteadress |
u32 Timeout = 0; |
u8 text[50]; |
u8 rsp[6]; // SD-SPI response buffer |
SD_Result_t result = SD_ERROR_UNKNOWN; |
if(SD_SWITCH) // init only if the SD-Switch is indicating a card in the slot |
{ |
SerialPutString("\r\n SSC init..."); |
SSC_Init(); |
SerialPutString("ok"); |
SerialPutString("\r\n SDC init..."); |
SDCardInfo.Valid = 0; |
/* The host shall supply power to the card so that the voltage is reached to Vdd_min within 250ms and |
start to supply at least 74 SD clocks to the SD card with keeping cmd line to high. In case of SPI |
mode, CS shall be held to high during 74 clock cycles. */ |
SSC_Disable(); // set SD_CS high |
SSC_ClearRxFifo(); // clear the rx fifo |
CMD[1] = ((addr & 0xFF000000) >>24 ); |
CMD[2] = ((addr & 0x00FF0000) >>16 ); |
CMD[3] = ((addr & 0x0000FF00) >>8 ); |
for (Timeout = 0; Timeout < 15; Timeout++) // 15*8 = 120 cycles |
{ |
SSC_PutChar(0xFF); |
} |
// switch to idle state |
while(SDC_SendCMDR1(CMD_GO_IDLE_STATE, 0UL) != R1_IDLE_STATE) |
{ |
if (Timeout++ > 20) |
{ |
SerialPutString("reset timeout"); |
result = SD_ERROR_RESET; |
goto end; |
} |
} |
// enable crc feature |
/* if(SDC_SendCMDR1(CMD_CRC_ON_OFF, 1UL) != R1_IDLE_STATE) |
{ |
sprintf(text,"Bad cmd59 R1=%02X.\r\n", rsp[0]); |
SerialPutString(text); |
result = SD_ERROR_BAD_RESPONSE; |
goto end; |
}*/ |
// check for card hw version |
// 2.7-3.6V Range = 0x01, check pattern 0xAA |
rsp[0] = SDC_SendCMDR1(CMD_SEND_IF_COND, 0x000001AA); |
// answer to cmd58 is an R7 response (R1+ 4Byte IFCond) |
if(rsp[0] & R1_BAD_RESPONSE) |
{ |
sprintf(text,"Bad cmd8 R1=%02X.\r\n", rsp[0]); |
SerialPutString(text); |
result = SD_ERROR_BAD_RESPONSE; |
goto end; |
} |
if(rsp[0] & R1_ILLEGAL_CMD) |
{ |
//Ver1.X SD Memory Card or not a SD Memory Card |
SDCardInfo.Version = VER_1X; |
} |
else |
{ |
// Ver2.00 or later SD Memory Card |
// reading the remaining bytes of the R7 response |
SDCardInfo.Version = VER_20; |
for(Timeout = 1; Timeout < 5; Timeout++) |
{ |
rsp[Timeout] = SSC_GetChar(); |
} |
//check pattern |
if(rsp[4]!= 0xAA) |
{ |
SerialPutString("Bad cmd8 R7 check pattern.\r\n"); |
result = SD_ERROR_BAD_RESPONSE; |
goto end; |
} |
if ( (rsp[3] & 0x0F)!= 0x01 ) // voltage range is not 2.7-3.6V |
{ |
SerialPutString("Card is incompatible to 3.3V.\r\n"); |
result = SD_ERROR_BAD_VOLTAGE_RANGE; |
goto end; |
} |
} |
rsp[0] = SDC_SendCMDR1(CMD_READ_OCR, 0UL); |
// answer to cmd58 is an R3 response (R1 + 4Byte OCR) |
if(rsp[0] & R1_BAD_RESPONSE) |
{ |
sprintf(text,"Bad cmd58 R1 %02x.\r\n", rsp[0]); |
SerialPutString(text); |
result = SD_ERROR_BAD_RESPONSE; |
goto end; |
} |
if(rsp[0] & R1_ILLEGAL_CMD) |
{ |
SerialPutString("Not an SD-CARD.\r\n"); |
result = SD_ERROR_NO_SDCARD; |
goto end; |
} |
// read 4 bytes of OCR register |
for(Timeout = 1; Timeout < 5; Timeout++) |
{ |
rsp[Timeout] = SSC_GetChar(); |
} |
// NavicCtrl uses 3.3 V, therefore check for bit 20 & 21 |
if((rsp[2] & 0x30) != 0x30) |
{ |
// supply voltage is not supported by sd-card |
SerialPutString("Card is incompatible to 3.3V.\r\n"); |
result = SD_ERROR_BAD_VOLTAGE_RANGE; |
goto end; |
} |
// Initialize the sd-card sending continously ACMD_SEND_OP_COND (only supported by SD cards) |
Timeout = SetDelay(2000); // set timeout to 2000 ms (large cards tend to longer) |
do |
{ |
rsp[0] = SDC_SendACMDR1(ACMD_SEND_OP_COND, 0UL); |
if(rsp[0] & R1_BAD_RESPONSE) |
{ |
sprintf(text,"Bad Acmd41 R1=%02X.\r\n", rsp[0]); |
SerialPutString(text); |
result = SD_ERROR_BAD_RESPONSE; |
goto end; |
} |
if(CheckDelay(Timeout)) |
{ |
SerialPutString("Init timeout.\r\n"); |
result = SD_ERROR_INITIALIZE; |
goto end; |
} |
} while(rsp[0] & R1_IDLE_STATE); // loop until idle state |
if(rsp[0] != R1_NO_ERR) |
{ |
SerialPutString("Init error.\r\n"); |
result = SD_ERROR_INITIALIZE; |
goto end; |
} |
/* set block size to 512 bytes */ |
if(SDC_SendCMDR1(CMD_SET_BLOCKLEN, 512UL) != R1_NO_ERR) |
{ |
SerialPutString("Error setting block length to 512.\r\n"); |
result = SD_ERROR_SET_BLOCKLEN; |
goto end; |
} |
tmp = SDC_PutCommand (CMD); // send command to sdcard. |
if (tmp != 0) |
{ |
return(tmp); |
} |
SSC_ClearRxFifo(); |
for (a=0;a<100;a++) // wait until sdcard is ready |
{ |
SSC_GetChar(); |
} |
//SSC_Disable(); // set SD_CS high |
// here is the right place to inrease the SPI boud rate to maximum |
//SSC_Enable(); // set SD_CS high |
// read CID register |
result = SDC_GetCID((u8 *)&SDCardInfo.CID); |
if(result != SD_SUCCESS) |
{ |
SerialPutString("Error reading CID.\r\n"); |
goto end; |
} |
SSC_PutChar(0xFE); // send start of header to the SSC |
// read CSD register |
result = SDC_GetCSD((u8 *)&SDCardInfo.CSD); |
if(result != SD_SUCCESS) |
{ |
SerialPutString("Error reading CSD.\r\n"); |
goto end; |
} |
for (a=0;a<512;a++) // transmitt one sector (normaly 512bytes) of data to the sdcard. |
SerialPutString("ok\r\n"); |
u8 c_size_mult, read_bl_len; |
u32 c_size; |
switch(SDCardInfo.CSD[0]>>6) // check CSD Version |
{ |
case 0x00: // if CSD is V1.0 structure (2GB limit) |
/* |
memory capacity = BLOCKNR * BLOCK_LEN |
BLOCKNR = (C_SIZE+1) * MULT |
MULT = 2^(C_SIZE_MULT+2) |
BLOCK_LEN = 2^READ_BL_LEN |
C_SIZE is 12 bits [73:62] in CSD register |
C_SIZE_MULT is 3 bits [49:47] in CSD register |
READ_BL_LEN is 4 bits [83:80] in CSD register |
*/ |
read_bl_len = (SDCardInfo.CSD[5] & 0x0F); //CSD[05] -> [87:80] |
c_size = ((u32)(SDCardInfo.CSD[6] & 0x03))<<10; //CSD[06] -> [79:72] |
c_size |= ((u32)SDCardInfo.CSD[7])<<2; //CSD[07] -> [71:64] |
c_size |= (u32)(SDCardInfo.CSD[8]>>6); //CSD[08] -> [63:56] |
c_size_mult = (SDCardInfo.CSD[9] & 0x03)<<1; //CSD[09] -> [55:48] |
c_size_mult |=(SDCardInfo.CSD[10] & 0x80)>>7; //CSD[10] -> [47:40] |
SDCardInfo.Capacity = (u32)(c_size+1)*(1L<<(c_size_mult+2))*(1L<<read_bl_len); |
break; |
case 0x01: // if CSD is V2.0 structure (HC SD-Card > 2GB) |
/* |
memory capacity = (C_SIZE+1) * 512K byte |
C_SIZE is 22 bits [69:48] in CSR register |
*/ |
c_size = ((u32)(SDCardInfo.CSD[7] & 0x3F))<<16; //CSD[07] -> [71:64] |
c_size |= ((u32)SDCardInfo.CSD[8])<<8; //CSD[08] -> [63:56] |
c_size |= (u32)SDCardInfo.CSD[9]; //CSD[09] -> [55:48]; |
SDCardInfo.Capacity = (c_size + 1)* 512L * 1024L; |
break; |
default: //unknown CSD Version |
SDCardInfo.Capacity = 0; |
break; |
} |
switch(SDCardInfo.Version) |
{ |
case VER_1X: |
SerialPutString(" SD-CARD V1.x"); |
break; |
case VER_20: |
SerialPutString(" SD-CARD V2.0 or later"); |
default: |
break; |
} |
u16 mb_size = (u16)(SDCardInfo.Capacity/(1024L*1024L)); |
sprintf(text, "\r\n Capacity = %i MB", mb_size); |
SerialPutString(text); |
// SDC_PrintCID((u8 *)&SDCardInfo.CID); |
SDCardInfo.Valid = 1; |
// jump point for error condition before |
end: |
SSC_Disable(); |
} |
else |
{ |
SSC_PutChar(*Buffer++); |
//SerialPutString("\r\nNo Card in Slot."); |
SSC_Deinit(); |
SDCardInfo.Valid = 0; |
result = SD_ERROR_NOCARD; |
} |
SSC_PutChar(0xFF); // write two bytes of crc to the sdcard (not used in spi-mode) |
SSC_PutChar(0xFF); |
SSC_ClearRxFifo(); |
while (SSC_GetChar() != 0xff){}; // wait untile the sdcard is ready. |
SSC_Disable(); // disable sdcard. |
if(result != SD_SUCCESS) SerialPutString("nok"); |
return(0); |
return(result); |
} |
//________________________________________________________________________________________________________________________________________ |
// Funtion: SDC_GetSector(u32 addr,u8 *Buffer); |
// Funtion: SDC_Deinit(void); |
// |
// Description: This function reads one sector of data from the SSC |
// Description: This function deinitialises the SDCard interface. |
// |
// |
// Returnvalue: none |
// Returnvalue: the function returns 0 if the initialisation was successfull otherwise the function returns an errorcode. |
//________________________________________________________________________________________________________________________________________ |
u8 SDC_GetSector(u32 addr,u8 *Buffer) |
{ |
u8 CMD[] = {0x51,0x00,0x00,0x00,0x00,0xFF}; |
addr = addr << 9; // convert sectoradress to byteadress. |
SD_Result_t SDC_Deinit(void) |
{ |
SerialPutString("SDC deinit..."); |
SSC_Deinit(); |
CMD[1] = ((addr & 0xFF000000) >>24 ); |
CMD[2] = ((addr & 0x00FF0000) >>16 ); |
CMD[3] = ((addr & 0x0000FF00) >>8 ); |
SDCardInfo.Valid = 0; |
SDCardInfo.Capacity = 0; |
SDCardInfo.Version = VER_UNKNOWN; |
// sprintf(text,"\n\rGetSector: (%lu)", (u32)addr ); SerialPutString(text); |
SDC_GetBlock(CMD,Buffer,512); // read specified sector from sdcard. |
return(0); |
SerialPutString("ok\r\n"); |
return(SD_SUCCESS); |
} |
//________________________________________________________________________________________________________________________________________ |
// Funtion: SDC_GetBlock(void); |
// Funtion: SDC_PutSector(void); |
// |
// Description: This function reads one block of data of int bytes from the SSC. |
// Description: This function writes one sector of data to the SSC |
// |
// |
// Returnvalue: the function returns 0 if the initialisation was successfull otherwise the function returns an errorcode. |
// Returnvalue: SD_Result_t |
//________________________________________________________________________________________________________________________________________ |
void SDC_GetBlock(u8 *CMD,u8 *Buffer,u16 Bytes) |
{ |
if (SDC_PutCommand (CMD) != 0) // Send command to the sdcard. |
SD_Result_t SDC_PutSector(u32 addr, const u8 *Buffer) |
{ |
u8 rsp; |
u16 timeout = 0; |
u16 a, Crc16; |
//u32 Timeout = 0; |
SD_Result_t result = SD_ERROR_UNKNOWN; |
addr = addr << 9; // convert sectoradress to byteadress |
rsp = SDC_SendCMDR1(CMD_WRITE_SINGLE_BLOCK, addr); |
if (rsp != R1_NO_ERR) |
{ |
return; |
result = SD_ERROR_BAD_RESPONSE; |
goto end; |
} |
SSC_ClearRxFifo(); |
// SerialPutString("\n\rWait."); |
while (SSC_GetChar() != 0xfe){}; // wait until the sdcard is ready to transmitt data. |
// SerialPutString("Ok."); |
u16 a; |
for (a=0;a<Bytes;a++) // read the block from the SSC (normaly 512Bytes) |
for (a=0;a<20;a++) // at least one byte |
{ |
*Buffer++ = SSC_GetChar(); |
SSC_GetChar(); |
} |
Crc16 = CRC16(Buffer, 512); // calc checksum for data block |
SSC_PutChar(DATA_START_TOKEN); // send data start of header to the SSC |
SSC_GetChar(); // Read two bytes CRC- checksum (not used in spi-mode) |
SSC_GetChar(); |
SSC_Disable(); // disable sdcard. |
for (a=0;a<512;a++) // transmit one sector (normaly 512bytes) of data to the sdcard. |
{ |
SSC_PutChar(Buffer[a]); |
} |
// write two bytes of crc16 to the sdcard |
SSC_PutChar((u8)(Crc16>>8)); // write high byte first |
SSC_PutChar((u8)(0x00FF&Crc16)); // lowbyte last |
SSC_ClearRxFifo(); |
do // wait for data response token |
{ |
rsp = SSC_GetChar(); |
if(timeout++>500) break; |
}while((rsp & 0x11) != 0x01 ); |
// analyse data response token |
switch(rsp & DATA_RESPONSE_MASK) |
{ |
case DATA_RESPONSE_OK: |
result = SD_SUCCESS; |
break; |
case DATA_RESPONSE_CRC_ERR: |
result = SD_ERROR_CRC_DATA; |
goto end; |
break; |
case DATA_RESPONSE_WRITE_ERR: |
result = SD_ERROR_WRITE_DATA; |
goto end; |
break; |
default: |
result = SD_ERROR_UNKNOWN; |
goto end; |
break; |
} |
// wait until the sdcard is busy. |
rsp = SDC_WaitForBusy(); |
if(rsp != 0xFF) |
{ |
result = SD_ERROR_TIMEOUT; |
goto end; |
} |
// check card status |
rsp = SDC_SendCMDR1(CMD_SEND_STATUS, 0); |
if(rsp != R1_NO_ERR) |
{ |
result = SD_ERROR_BAD_RESPONSE; |
SSC_GetChar(); |
goto end; |
} |
// 2nd byte of r2 response |
rsp = SSC_GetChar(); |
if(rsp != R2_NO_ERR) |
{ |
result = SD_ERROR_WRITE_DATA; |
SSC_GetChar(); |
goto end; |
} |
end: |
//SSC_Disable(); // disable sdcard. |
if(result != SD_SUCCESS) |
{ |
sprintf(text,"Error %02X writing data to sd card (R=%02X).\r\n", result, rsp); |
SerialPutString(text); |
} |
return(result); |
} |
//________________________________________________________________________________________________________________________________________ |
// Funtion: SDC_GetSector(u32 addr,u8 *Buffer); |
// |
// Description: This function reads one sector of data from the SSC |
// |
// |
// Returnvalue: SD_Result_t |
//________________________________________________________________________________________________________________________________________ |
SD_Result_t SDC_GetSector(u32 addr,u8 *Buffer) |
{ |
addr = addr << 9; // convert sectoradress to byteadress |
return SDC_GetData(CMD_READ_SINGLE_BLOCK, addr, Buffer, 512); |
} |
/trunk/sdc.h |
---|
1,33 → 1,36 |
#ifndef _SDC_H_ |
#define _SDC_H_ |
#ifndef _SDC_H |
#define _SDC_H |
extern unsigned char SDC_Init(void); |
#include "91x_lib.h" |
//________________________________________________________________________________________________________________________________________ |
// |
// Functions needed for access to the sdcard. |
// Functions needed for accessing the sdcard. |
// |
//________________________________________________________________________________________________________________________________________ |
extern unsigned char SSC_GetChar(void); |
extern void SSC_PutChar(u8); |
extern void MMC_Read_Block(u8 *,u8 *,u16); |
typedef enum |
{ |
SD_SUCCESS = 0, |
SD_ERROR_NOCARD, |
SD_ERROR_RESET, |
SD_ERROR_INITIALIZE, |
SD_ERROR_BAD_RESPONSE, |
SD_ERROR_BAD_VOLTAGE_RANGE, |
SD_ERROR_NO_SDCARD, |
SD_ERROR_TIMEOUT, |
SD_ERROR_CRC_DATA, |
SD_ERROR_WRITE_DATA, |
SD_ERROR_READ_DATA, |
SD_ERROR_SET_BLOCKLEN, |
SD_ERROR_UNKNOWN |
} SD_Result_t; |
extern SD_Result_t SDC_Init(void); |
extern SD_Result_t SDC_GetSector (u32 ,u8 *); |
extern SD_Result_t SDC_PutSector (u32, const u8 *); |
extern SD_Result_t SDC_Deinit(void); |
//________________________________________________________________________________________________________________________________________ |
// |
// Functions needed internaly for the fat16 implementation |
// |
//________________________________________________________________________________________________________________________________________ |
#endif // _SDC_H |
extern unsigned char SDC_GetSector (u32,u8 *); |
extern unsigned char SDC_PutSector (u32,u8 *); |
extern unsigned char SDC_PutCommand (u8 *); |
extern void SDC_GetBlock(u8 *CMD,u8 *Buffer,u16 Bytes); |
#define nop() __asm__ __volatile__ ("nop" ::) |
#endif |
/trunk/ssc.c |
---|
54,10 → 54,10 |
// + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
// + POSSIBILITY OF SUCH DAMAGE. |
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
#include "main.h" |
#include "91x_lib.h" |
//________________________________________________________________________________________________________________________________________ |
// Module name: fat16.c |
// Module name: ssc.c |
// Compiler used: avr-gcc 3.4.5 |
// Last Modifikation: 24.07.2007 |
// Version: 1.02 |
65,16 → 65,13 |
// Description: Source files for access to the synchrnous serial channel. |
// Copyright (C) 2007 Stephan Busker |
//........................................................................................................................................ |
// Functions: extern void SSC_Init(void); |
// extern u8 SSC_GetChar (void); |
// ext. Functions: extern void SSC_Init(void); |
// extern u8 SSC_GetChar (void); |
// extern void SSC_PutChar (u8 Byte); |
// extern void SSC_Disable(void); |
// extern void SSC_Enable(void); |
// extern void SSC_ClearRxFifo(); |
//........................................................................................................................................ |
// ext. functions: extern u8 SDC_GetSector (unsigned long,u8 *); |
// extern u8 SDC_PutSector (unsigned long,u8 *); |
//........................................................................................................................................ |
// |
// URL: www.Mikro-Control.de |
// mailto: stephan.busker@mikro-control.de |
//________________________________________________________________________________________________________________________________________ |
81,10 → 78,40 |
//________________________________________________________________________________________________________________________________________ |
// Function: SSC_Enable(void); |
// |
// Description: This function enables chipselect of the sdcard (active low) |
// |
// |
// Returnvalue: none |
//________________________________________________________________________________________________________________________________________ |
void SSC_Enable(void) |
{ |
// enable chipselect of the sd-card (P5.4 -> SD-CS, active low). |
GPIO_WriteBit(GPIO5, GPIO_Pin_4 , Bit_RESET); |
} |
//________________________________________________________________________________________________________________________________________ |
// Funtion: SSC_Init(void); |
// Function: SSC_Disable(void); |
// |
// Description: This function disables chipselect of the sdcard (active low) |
// |
// |
// Returnvalue: none |
//________________________________________________________________________________________________________________________________________ |
void SSC_Disable(void) |
{ |
// disable chipselect of the sd-card (P5.4 -> SD-CS, active low). |
GPIO_WriteBit(GPIO5, GPIO_Pin_4 , Bit_SET); |
} |
//________________________________________________________________________________________________________________________________________ |
// Function: SSC_Init(void); |
// |
// Description: This function initialises the synchronus serial channel to the sdcard. |
// |
// |
93,69 → 120,119 |
void SSC_Init(void) |
{ |
GPIO_InitTypeDef GPIO_InitStructure; |
SSP_InitTypeDef SSP_InitStructure; |
WIU_InitTypeDef WIU_InitStructure; |
// enable APB clock for SPI1 |
SCU_APBPeriphClockConfig(__SSP1 ,ENABLE); |
// configure P5.4 -> SD-CS as an output pin |
GPIO_InitStructure.GPIO_Direction = GPIO_PinOutput; |
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; |
GPIO_InitStructure.GPIO_Type = GPIO_Type_PushPull ; |
GPIO_InitStructure.GPIO_IPConnected = GPIO_IPConnected_Disable; |
GPIO_InitStructure.GPIO_Alternate = GPIO_OutputAlt1; |
GPIO_Init (GPIO5, &GPIO_InitStructure); |
// configure P3.4 -> SCK1 and P3.6 -> MOSI1 as an output pin |
GPIO_InitStructure.GPIO_Direction = GPIO_PinOutput; |
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_6; |
GPIO_InitStructure.GPIO_Type = GPIO_Type_PushPull ; |
GPIO_InitStructure.GPIO_IPConnected = GPIO_IPConnected_Enable; |
GPIO_InitStructure.GPIO_Alternate = GPIO_OutputAlt2; |
GPIO_Init (GPIO3, &GPIO_InitStructure); |
// configure P3.5 <- MISO1 as an input pin |
GPIO_InitStructure.GPIO_Direction = GPIO_PinInput; |
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; |
GPIO_InitStructure.GPIO_Type = GPIO_Type_PushPull; |
GPIO_InitStructure.GPIO_IPConnected = GPIO_IPConnected_Enable; |
GPIO_InitStructure.GPIO_Alternate = GPIO_InputAlt1; |
GPIO_Init (GPIO3, &GPIO_InitStructure); |
// configure SPI1 |
SSP_DeInit(SSP1); |
SSP_StructInit(&SSP_InitStructure); |
SSP_InitStructure.SSP_FrameFormat = SSP_FrameFormat_Motorola; |
SSP_InitStructure.SSP_Mode = SSP_Mode_Master; |
SSP_InitStructure.SSP_CPHA = SSP_CPHA_1Edge; |
SSP_InitStructure.SSP_CPOL = SSP_CPOL_Low; |
// Set Baud Rate (Prescaler) |
// bit rate is BRCLK/SSP_ClockPrescaler/(1+SSP_ClockRate)) |
// With MSCLK = 48MHz/2 = BRCLK we get for the SPICLK = 24Mhz / 8 / (1+5) = 500 kHz |
SSP_InitStructure.SSP_ClockRate = 14; //5 |
SSP_InitStructure.SSP_ClockPrescaler = 8; |
SSP_Init(SSP1, &SSP_InitStructure); |
SSC_Disable(); |
SSP_Cmd(SSP1, ENABLE); |
SerialPutString("SPI1 init..."); |
GPIO_InitTypeDef GPIO_InitStructure; |
SSP_InitTypeDef SSP_InitStructure; |
// Configure SD_SWITCH at pin GPIO5.3 as an external irq 11 |
SCU_APBPeriphClockConfig(__SSP1 ,ENABLE); |
// GPIO_DeInit(GPIO2); |
GPIO_InitStructure.GPIO_Direction = GPIO_PinOutput; |
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_6; |
GPIO_InitStructure.GPIO_Type = GPIO_Type_PushPull ; |
GPIO_InitStructure.GPIO_IPConnected = GPIO_IPConnected_Enable; |
GPIO_InitStructure.GPIO_Alternate = GPIO_OutputAlt2; |
GPIO_Init (GPIO3, &GPIO_InitStructure); |
// configure the port |
SCU_APBPeriphClockConfig(__GPIO5, ENABLE); // Enable the GPIO5 Clock |
GPIO_InitStructure.GPIO_Direction = GPIO_PinInput; |
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; |
GPIO_InitStructure.GPIO_Type = GPIO_Type_PushPull ; |
GPIO_InitStructure.GPIO_IPConnected = GPIO_IPConnected_Disable; |
GPIO_InitStructure.GPIO_Alternate = GPIO_InputAlt1; |
GPIO_Init(GPIO5, &GPIO_InitStructure); |
// configure the EXT11 interrupt line (P5.3) as an IRQ with the lowest priority |
SCU_APBPeriphClockConfig(__WIU, ENABLE); |
WIU_Cmd(ENABLE ); |
WIU_ClearITPendingBit(WIU_Line11); |
WIU_DeInit(); |
WIU_InitStructure.WIU_TriggerEdge = WIU_FallingEdge; |
WIU_InitStructure.WIU_Line = WIU_Line11; |
WIU_Init(&WIU_InitStructure); |
// The EXTIT1_IRQHandler() is called every time the SD-Switch is activated (falling edge) |
// by inserting an sd-card |
SCU_WakeUpLineConfig(11); |
VIC_Config(EXTIT1_ITLine, VIC_IRQ, 7); |
VIC_ITCmd(EXTIT1_ITLine, ENABLE); |
} |
GPIO_InitStructure.GPIO_Direction = GPIO_PinOutput; |
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; |
GPIO_InitStructure.GPIO_Type = GPIO_Type_PushPull ; |
GPIO_InitStructure.GPIO_IPConnected = GPIO_IPConnected_Disable; |
GPIO_InitStructure.GPIO_Alternate = GPIO_OutputAlt1; |
GPIO_Init (GPIO5, &GPIO_InitStructure); |
void SSC_Deinit(void) |
{ |
GPIO_InitTypeDef GPIO_InitStructure; |
GPIO_InitStructure.GPIO_Direction = GPIO_PinInput; |
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; |
GPIO_InitStructure.GPIO_Type = GPIO_Type_PushPull; |
GPIO_InitStructure.GPIO_IPConnected = GPIO_IPConnected_Enable; |
GPIO_InitStructure.GPIO_Alternate = GPIO_InputAlt1; |
GPIO_Init (GPIO3, &GPIO_InitStructure); |
SSP_DeInit(SSP1); |
SSP_StructInit(&SSP_InitStructure); |
SSP_InitStructure.SSP_FrameFormat = SSP_FrameFormat_Motorola; |
SSP_InitStructure.SSP_Mode = SSP_Mode_Master; |
SSP_InitStructure.SSP_CPHA = SSP_CPHA_1Edge; |
SSP_InitStructure.SSP_CPOL = SSP_CPOL_Low; |
// Hier muss die Baudrate noch richtig eingestellt werden (mit Prescaler) |
SSP_InitStructure.SSP_ClockRate = 5; |
SSP_InitStructure.SSP_ClockPrescaler = 8; |
SSP_Init(SSP1, &SSP_InitStructure); |
SSC_Disable(); |
SSP_Cmd(SSP1, ENABLE); |
/* MMC_Direction_REG &=~(1<<SPI_DI); // Set the direction of the ssc-port |
MMC_Direction_REG |= (1<<SPI_Clock); // _______ _______ |
MMC_Direction_REG |= (1<<SPI_DO); // CS \________________________/ |
MMC_Direction_REG |= (1<<MMC_Chip_Select); // |
MMC_Direction_REG |= (1<<SPI_SS); // ___ ___ ___ |
// clk __________/ \___/ \___/ \_________ |
// |
// ___ ___ |
// data_________/ \___________/ \___________ |
SSP_Cmd(SSP1, DISABLE); |
SSP_DeInit(SSP1); |
// initialise ssc, clock = Idel low |
// devide clock by 32 |
SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR1)|(1<<CPOL); // Enable SSC in mastermode, invert clockpolarity (idle high) |
SPSR = SPSR|(1<<SPI2X);*/ |
SerialPutString("ok\n\r"); |
// configure P5.4 -> SD-CS as an input pin |
GPIO_InitStructure.GPIO_Direction = GPIO_PinInput; |
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; |
GPIO_InitStructure.GPIO_Type = GPIO_Type_PushPull ; |
GPIO_InitStructure.GPIO_IPConnected = GPIO_IPConnected_Disable; |
GPIO_InitStructure.GPIO_Alternate = GPIO_InputAlt1; |
GPIO_Init (GPIO5, &GPIO_InitStructure); |
// configure P3.4 -> SCK1 and P3.6 -> MOSI1 as an input pin |
GPIO_InitStructure.GPIO_Direction = GPIO_PinInput; |
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_6; |
GPIO_InitStructure.GPIO_Type = GPIO_Type_PushPull ; |
GPIO_InitStructure.GPIO_IPConnected = GPIO_IPConnected_Disable; |
GPIO_InitStructure.GPIO_Alternate = GPIO_InputAlt1; |
GPIO_Init (GPIO3, &GPIO_InitStructure); |
// configure P3.5 <- MISO1 as an input pin |
GPIO_InitStructure.GPIO_Direction = GPIO_PinInput; |
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; |
GPIO_InitStructure.GPIO_Type = GPIO_Type_PushPull; |
GPIO_InitStructure.GPIO_IPConnected = GPIO_IPConnected_Disable; |
GPIO_InitStructure.GPIO_Alternate = GPIO_InputAlt1; |
GPIO_Init (GPIO3, &GPIO_InitStructure); |
// disable APB clock for SPI1 |
SCU_APBPeriphClockConfig(__SSP1 ,DISABLE); |
// configure the port of the SDC-Switch |
SCU_APBPeriphClockConfig(__GPIO5, ENABLE); // Enable the GPIO5 Clock |
GPIO_InitStructure.GPIO_Direction = GPIO_PinInput; |
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; |
GPIO_InitStructure.GPIO_Type = GPIO_Type_PushPull ; |
GPIO_InitStructure.GPIO_IPConnected = GPIO_IPConnected_Disable; |
GPIO_InitStructure.GPIO_Alternate = GPIO_InputAlt1; |
GPIO_Init(GPIO5, &GPIO_InitStructure); |
} |
//________________________________________________________________________________________________________________________________________ |
// Funtion: SSC_GetChar(void); |
// Function: SSC_GetChar(void); |
// |
// Description: This function reads one byte from the SSC |
// |
166,29 → 243,23 |
u8 SSC_GetChar (void) |
{ |
u8 Byte = 0; |
// SerialPutString("\n\rGetChar."); |
SSP_SendData(SSP1, 0xFF); |
while(SSP_GetFlagStatus(SSP1, SSP_FLAG_TxFifoEmpty) != SET); |
Byte = SSP_ReceiveData(SSP1); |
/* SPDR = 0x00; // read one byte of data from the SSC |
while(!(SPSR & (1<<SPIF))){}; // wait until the data has been read. |
Byte = SPDR; |
*/ |
// sprintf(text," %02X ", Byte); SerialPutString(text);SerialPutString("done."); |
while(SSP_GetFlagStatus(SSP1, SSP_FLAG_TxFifoNotFull) != SET); // wait for space in the tx fifo |
SSP_SendData(SSP1, 0xFF);// send dymmy byte (0xFF) as master to receive a byte from the slave |
while(SSP_GetFlagStatus(SSP1, SSP_FLAG_TxFifoEmpty) != SET); // wait for the byte to be sent |
Byte = SSP_ReceiveData(SSP1); // read the byte transmitted from the slave |
return (Byte); |
} |
//________________________________________________________________________________________________________________________________________ |
void SSC_ClearRxFifo (void) |
{ |
// SerialPutString("\n\rClr RxFifo "); |
// wait that the tx fifo is empty |
while(SSP_GetFlagStatus(SSP1, SSP_FLAG_TxFifoEmpty) != SET); |
// then empty the rx fifo by reading all the bytes that are available |
while(SSP_GetFlagStatus(SSP1, SSP_FLAG_RxFifoNotEmpty) == SET) SSP_ReceiveData(SSP1); |
// SerialPutString("done."); |
} |
//________________________________________________________________________________________________________________________________________ |
// Funtion: SSC_PutChar(u8 Byte); |
// Function: SSC_PutChar(u8 Byte); |
// |
// Description: This function writes one byte to the SSC |
// |
198,43 → 269,16 |
void SSC_PutChar (u8 Byte) |
{ |
//SerialPutString("\n\rPutChar."); sprintf(text," %02X ", Byte); SerialPutString(text); |
// wait for some space in the tx fifo |
while(SSP_GetFlagStatus(SSP1, SSP_FLAG_TxFifoNotFull) != SET); |
// put the byte to send in the tx fifo |
SSP_SendData(SSP1, Byte); |
//SerialPutString("done."); |
} |
//________________________________________________________________________________________________________________________________________ |
// Funtion: SSC_Disable(void); |
// |
// Description: This function enables chipselect of the sdcard (active low) |
// |
// |
// Returnvalue: none |
//________________________________________________________________________________________________________________________________________ |
void SSC_Disable(void) |
{ |
//MMC_Write &= ~(1<<MMC_Chip_Select); // disable chipselect of the sdcard (active low). |
GPIO_WriteBit(GPIO5, GPIO_Pin_4 , Bit_SET); |
} |
//________________________________________________________________________________________________________________________________________ |
// Funtion: SSC_Enable(void); |
// |
// Description: This function disables chipselect of the sdcard (active low) |
// |
// |
// Returnvalue: none |
//________________________________________________________________________________________________________________________________________ |
void SSC_Enable(void) |
{ |
//MMC_Write |= (1<<MMC_Chip_Select); // enable chipselect of the sdcard (active low). |
GPIO_WriteBit(GPIO5, GPIO_Pin_4 , Bit_RESET); |
} |
/trunk/ssc.h |
---|
1,50 → 1,23 |
#ifndef __SSC_H |
#define __SSC_H |
#ifndef _SSC_H |
#define _SSC_H |
#define MMC_Write PORTB //Port an der die MMC/SD-Karte angeschlossen ist also des SPI |
#define MMC_Read PINB |
#define MMC_Direction_REG DDRB |
#if defined (__AVR_ATmega128__) |
#define SPI_DI 3 //Port Pin an dem Data Output der MMC/SD-Karte angeschlossen ist |
#define SPI_DO 2 //Port Pin an dem Data Input der MMC/SD-Karte angeschlossen ist |
#define SPI_Clock 1 //Port Pin an dem die Clock der MMC/SD-Karte angeschlossen ist (clk) |
#define MMC_Chip_Select 4 //Port Pin an dem Chip Select der MMC/SD-Karte angeschlossen ist |
#define SPI_SS 0 //Nicht Benutz muß aber definiert werden |
#endif |
#if defined (__AVR_ATmega32__) |
#define SPI_DI 6 //Port Pin an dem Data Output der MMC/SD-Karte angeschlossen ist |
#define SPI_DO 5 //Port Pin an dem Data Input der MMC/SD-Karte angeschlossen ist |
#define SPI_Clock 7 //Port Pin an dem die Clock der MMC/SD-Karte angeschlossen ist (clk) |
#define MMC_Chip_Select 3 //Port Pin an dem Chip Select der MMC/SD-Karte angeschlossen ist |
#define SPI_SS 4 //Nicht Benutz muß aber definiert werden |
#endif |
#if defined (__AVR_ATmega644__) |
#define SPI_DI 6 //Port Pin an dem Data Output der MMC/SD-Karte angeschlossen ist |
#define SPI_DO 5 //Port Pin an dem Data Input der MMC/SD-Karte angeschlossen ist |
#define SPI_Clock 7 //Port Pin an dem die Clock der MMC/SD-Karte angeschlossen ist (clk) |
#define MMC_Chip_Select 4 //Port Pin an dem Chip Select der MMC/SD-Karte angeschlossen ist |
#define SPI_SS 3 //Nicht Benutz muß aber definiert werden |
#endif |
#include "91x_lib.h" |
//________________________________________________________________________________________________________________________________________ |
// |
// Functions needed for accessing the sdcard. |
// Functions needed for accessing the sdcard low level via SPI. |
// |
//________________________________________________________________________________________________________________________________________ |
extern void SSC_Init(void); |
extern unsigned char SSC_GetChar (void); |
extern void SSC_PutChar (unsigned char); |
extern void SSC_Enable(void); |
extern void SSC_Disable(void); |
extern void SSC_ClearRxFifo(void); |
#define SD_SWITCH !(GPIO_ReadBit(GPIO5, GPIO_Pin_3)) |
extern void SSC_Init(void); |
extern void SSC_Deinit(void); |
extern u8 SSC_GetChar (void); |
extern void SSC_PutChar (u8); |
extern void SSC_Enable(void); |
extern void SSC_Disable(void); |
extern void SSC_ClearRxFifo(void); |
#endif |
#endif //_SSC_H |