code cleanup

This commit is contained in:
David Voswinkel 2009-08-10 19:26:01 +02:00
parent 4a0740dd02
commit 8656beb769
8 changed files with 1262 additions and 856 deletions

File diff suppressed because it is too large Load Diff

View File

@ -1,76 +1,77 @@
#ifndef _FAT_H
#define _FAT_H
#define _FAT_H
// **************************************************************************************************************************
// WICHTIGE SCHLATER: -> hier kann die code größe angepasst werden, zu lasten der funktionalität !
#define SMALL_FILE_SYSTEM 0 // wenn 1 dann ist kleines file system, wenn 0 dann komplette file unterstützung !
#define WRITE 1 // wenn 1 dann ist write an, wenn 0 dann read only !
#define OVER_WRITE 1 // wenn 1 dann kann ffwrite dateien überschreiben (nicht performant), wenn 0 dann nur normales schreiben !
#define MAX_CLUSTERS_IN_ROW 256 // gibt an wie viele cluster am stück ohne fat lookup geschrieben bzw gelesen werden können, wenn die fat nicht fragmentiert ist !
// 1. fat_getFreeRowOfCluster -> fat_getFreeRowOfDir -> fat_makeRowDataEntry -> fat_makeFileEntry -> fat_writeSector "eintrag gemacht !!"
// 2. fat_loadSector -> fat_loadRowOfSector -> fat_loadFileDataFromCluster -> fat_loadFileDataFromDir (-> fat_cd) "daten chain"
#define SMALL_FILE_SYSTEM 0 // wenn 1 dann ist kleines file system, wenn 0 dann komplette file unterstützung !
#define WRITE 1 // wenn 1 dann ist write an, wenn 0 dann read only !
#define OVER_WRITE 1 // wenn 1 dann kann ffwrite dateien überschreiben (nicht performant), wenn 0 dann nur normales schreiben !
#define MAX_CLUSTERS_IN_ROW 256 // gibt an wie viele cluster am stück ohne fat lookup geschrieben bzw gelesen werden können, wenn
// die fat nicht fragmentiert ist !
// 1. fat_getFreeRowOfCluster -> fat_getFreeRowOfDir -> fat_makeRowDataEntry -> fat_makeFileEntry -> fat_writeSector "eintrag gemacht !!"
// 2. fat_loadSector -> fat_loadRowOfSector -> fat_loadFileDataFromCluster -> fat_loadFileDataFromDir (-> fat_cd) "daten chain"
// **************************************************************************************************************************
// funktionen
extern unsigned long int fat_clustToSec(unsigned long int); // rechnet cluster zu 1. sektor des clusters um
extern unsigned long int fat_secToClust(unsigned long int sec); // rechnet sektor zu cluster um!
extern unsigned long int fat_getNextCluster(unsigned long int oneCluster); // fat auf nächsten, verketteten cluster durchsuchen
extern unsigned char fat_initfat(void); // initalisierung (durchsucht MBR oder nicht)
extern unsigned char fat_writeSector(unsigned long int sec); // schreibt sektor auf karte
extern void fat_setCluster(unsigned long int cluster, unsigned long int content); // setzt cluster inhalt in der fat
extern void fat_delClusterChain(unsigned long int startCluster); // löscht cluster-chain in der fat
extern void fat_getFreeRowOfDir(unsigned long int dir); // durchsucht directory nach feiem eintrag
extern void fat_makeFileEntry(char name[],unsigned char attrib,unsigned long int length);
extern unsigned char fat_loadSector(unsigned long int sec); // läd übergebenen absoluten sektor
extern unsigned char fat_loadFileDataFromDir(char name[]); // durchsucht das aktuelle directory
extern unsigned char fat_cd(char *); // wechselt directory (start im rootDir)
extern unsigned char fat_loadFatData(unsigned long int); // läd fat daten
extern unsigned char fat_getFreeRowOfCluster(unsigned long secStart);// durchsucht cluster nach freiem eintrag
extern void fat_getFreeClustersInRow(unsigned long int offsetCluster); // sucht zusammenhängende freie cluster aus der fat
extern void fat_getFatChainClustersInRow(unsigned long int offsetCluster); // sucht fat-chain cluster die zusammenhängen
extern void fat_makeRowDataEntry(unsigned int row,char name[],unsigned char attrib,unsigned long int cluster,unsigned long int length);
extern unsigned char fat_loadRowOfSector(unsigned int); // läd reihe des geladen sektors auf struct:file
extern unsigned char fat_loadFileDataFromCluster(unsigned long int sec , char name[]); // durchsucht die reihen des geladenen sektors
extern void fat_setClusterChain(unsigned long int newOffsetCluster,unsigned int length);
extern char *fat_str(char *str); // wandelt einen string so, dass er der fat konvention entspricht !
extern unsigned long int fat_clustToSec(unsigned long int); // rechnet cluster zu 1. sektor des clusters um
extern unsigned long int fat_secToClust(unsigned long int sec); // rechnet sektor zu cluster um!
extern unsigned long int fat_getNextCluster(unsigned long int oneCluster); // fat auf nächsten, verketteten cluster durchsuchen
extern unsigned char fat_initfat(void); // initalisierung (durchsucht MBR oder nicht)
extern unsigned char fat_writeSector(unsigned long int sec); // schreibt sektor auf karte
extern void fat_setCluster(unsigned long int cluster, unsigned long int content); // setzt cluster inhalt in der fat
extern void fat_delClusterChain(unsigned long int startCluster); // löscht cluster-chain in der fat
extern void fat_getFreeRowOfDir(unsigned long int dir); // durchsucht directory nach feiem eintrag
extern void fat_makeFileEntry(char name[], unsigned char attrib,
unsigned long int length);
extern unsigned char fat_loadSector(unsigned long int sec); // läd übergebenen absoluten sektor
extern unsigned char fat_loadFileDataFromDir(char name[]); // durchsucht das aktuelle directory
extern unsigned char fat_cd(char *); // wechselt directory (start im rootDir)
extern unsigned char fat_loadFatData(unsigned long int); // läd fat daten
extern unsigned char fat_getFreeRowOfCluster(unsigned long secStart); // durchsucht cluster nach freiem eintrag
extern void fat_getFreeClustersInRow(unsigned long int offsetCluster); // sucht zusammenhängende freie cluster aus der fat
extern void fat_getFatChainClustersInRow(unsigned long int offsetCluster); // sucht fat-chain cluster die zusammenhängen
extern void fat_makeRowDataEntry(unsigned int row, char name[],
unsigned char attrib,
unsigned long int cluster,
unsigned long int length);
extern unsigned char fat_loadRowOfSector(unsigned int); // läd reihe des geladen sektors auf struct:file
extern unsigned char fat_loadFileDataFromCluster(unsigned long int sec, char name[]); // durchsucht die reihen des geladenen sektors
extern void fat_setClusterChain(unsigned long int newOffsetCluster,
unsigned int length);
extern char *fat_str(char *str); // wandelt einen string so, dass er der fat konvention entspricht !
// **************************************************************************************************************************
// **************************************************************************************************************************
// variablen
extern struct Fat{ // fat daten (1.cluster, root-dir, dir usw.)
unsigned char sector[512]; // der puffer für sektoren !
unsigned char bufferDirty; // puffer wurde beschrieben, sector muss geschrieben werden bevor er neu geladen wird
unsigned long int currentSectorNr;// aktuell geladener Sektor (in sector) //beschleunigt wenn z.b 2* 512 byte puffer vorhanden, oder bei fat operationen im gleichen sektor
unsigned long int dir; // Direktory zeiger rootDir=='0' sonst(1.Cluster des dir; start auf root)
unsigned long int rootDir; // Sektor(f16)/Cluster(f32) nr root directory
unsigned long int dataDirSec; // Sektor nr data area
unsigned long int fatSec; // Sektor nr fat area
unsigned long int startSectors; // der erste sektor in einer reihe (freie oder verkettete)
unsigned long int endSectors;
unsigned char secPerClust; // anzahl der sektoren pro cluster
unsigned char fatType; // fat16 oder fat32 (16 oder 32)
}fat;
extern struct Fat { // fat daten (1.cluster, root-dir, dir usw.)
unsigned char sector[512]; // der puffer für sektoren !
unsigned char bufferDirty; // puffer wurde beschrieben, sector muss geschrieben werden bevor er neu geladen wird
unsigned long int currentSectorNr; // aktuell geladener Sektor (in sector) //beschleunigt wenn z.b 2* 512 byte puffer vorhanden, oder
// bei fat operationen im gleichen sektor
unsigned long int dir; // Direktory zeiger rootDir=='0' sonst(1.Cluster des dir; start auf root)
unsigned long int rootDir; // Sektor(f16)/Cluster(f32) nr root directory
unsigned long int dataDirSec; // Sektor nr data area
unsigned long int fatSec; // Sektor nr fat area
unsigned long int startSectors; // der erste sektor in einer reihe (freie oder verkettete)
unsigned long int endSectors;
unsigned char secPerClust; // anzahl der sektoren pro cluster
unsigned char fatType; // fat16 oder fat32 (16 oder 32)
} fat;
extern struct File{ // datei infos
unsigned int cntOfBytes; // -nicht direkt aus dem dateisystem- zäht geschriebene bytes eines sektors
unsigned char name[13]; // 0,10 datei Name.ext (8.3 = max 11)(MUSS unsigned char weil E5)
unsigned char attrib; // 11,1 datei Attribut: 8=value name, 32=datei, 16=Verzeichniss, 15=linux kleingeschrieben eintrag
unsigned char row; // reihe im sektor in der die datei infos stehen (reihe 0-15)
unsigned long int firstCluster; // 20,2 /26,2 datei 1.cluster hi,low(möglicherweise der einzige) (4-byte)
unsigned long int length; // 28,4 datei Länge (4-byte)
unsigned long int lastCluster; // -nicht direkt aus dem dateisystem- letzter cluster der ersten kette
unsigned long int seek; // schreib position in der datei
}file;
extern struct File { // datei infos
unsigned int cntOfBytes; // -nicht direkt aus dem dateisystem- zäht geschriebene bytes eines sektors
unsigned char name[13]; // 0,10 datei Name.ext (8.3 = max 11)(MUSS unsigned char weil E5)
unsigned char attrib; // 11,1 datei Attribut: 8=value name, 32=datei, 16=Verzeichniss, 15=linux kleingeschrieben eintrag
unsigned char row; // reihe im sektor in der die datei infos stehen (reihe 0-15)
unsigned long int firstCluster; // 20,2 /26,2 datei 1.cluster hi,low(möglicherweise der einzige) (4-byte)
unsigned long int length; // 28,4 datei Länge (4-byte)
unsigned long int lastCluster; // -nicht direkt aus dem dateisystem- letzter cluster der ersten kette
unsigned long int seek; // schreib position in der datei
} file;
#endif

View File

@ -1,4 +1,4 @@
#include <string.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
@ -8,7 +8,7 @@
//*******************************************************************************************************************************
// *******************************************************************************************************************************
// 2 möglichkeiten beim öffnen, datei existiert(return 1) oder muss angelegt werden(return 2)
// zuerst wird geprüft ob es die datei im verzeichniss gibt. danach wird entschieden, ob die datei geöffnet wird oder angelegt.
// -beim offnen werden die bekannten cluster gesucht maximal MAX_CLUSTERS_IN_ROW in reihe. dann wird der 1. sektor der datei auf
@ -16,55 +16,58 @@
// -beim anlegen werden freie cluster gesucht, maximal MAX_CLUSTERS_IN_ROW in reihe. dann wird das struct file gefüllt.
// danach wird der dateieintrag gemacht(auf karte). dort wird auch geprüft ob genügend platz im aktuellen verzeichniss existiert.
// möglicherweise wird der 1. cluster der datei nochmal geändert. jetzt ist der erste frei sektor bekannt und es kann geschrieben werden.
//*******************************************************************************************************************************
unsigned char ffopen(char name[]){
// *******************************************************************************************************************************
unsigned char ffopen(char name[])
{
unsigned char file_flag=fat_loadFileDataFromDir(name); //prüfung ob datei vorhanden und evetuelles laden des file struct
unsigned char file_flag = fat_loadFileDataFromDir(name); // prüfung ob datei vorhanden und evetuelles laden des file struct
if( file_flag==0 ){ /** Datei existiert, anlegen nicht nötig! **/
fat_getFatChainClustersInRow( file.firstCluster ); // verkettete cluster aus der fat-chain suchen.
fat_loadSector( fat_clustToSec(file.firstCluster) ); // lät die ersten 512 bytes der datei auf puffer:sector.
file.lastCluster=fat_secToClust(fat.endSectors); // letzter bekannter cluster der datei
return 1;
}
#if (WRITE==1) // anlegen ist schreiben !
else{ /** Datei existiert nicht, also anlegen ! (nur wenn schreiben option an ist)**/
fat_getFreeClustersInRow(2); // leere cluster suchen, ab cluster 2.
strcpy((char*)file.name,(char*)name); // --- füllen des file struct, zum abschließenden schreiben.
file.firstCluster=fat_secToClust(fat.startSectors); // 1. cluster der datei
file.lastCluster=file.firstCluster;//fat_secToClust(fat.endSectors); // letzter bekannter cluster der datei
file.attrib=32; // --- file.row wird in der funktion fat_getFreeRowOfDir geschrieben !!
file.length=0; // damit da nix drin steht ^^
fat_makeFileEntry((char *)file.name,file.attrib,0); // DATEI ANLEGEN auf karte
fat.currentSectorNr=fat_clustToSec(file.firstCluster); // setzen des ersten sektors
return 2;
}
#endif
if (file_flag == 0) { /** Datei existiert, anlegen nicht nötig! **/
fat_getFatChainClustersInRow(file.firstCluster); // verkettete cluster aus der fat-chain suchen.
fat_loadSector(fat_clustToSec(file.firstCluster)); // lät die ersten 512 bytes der datei auf puffer:sector.
file.lastCluster = fat_secToClust(fat.endSectors); // letzter bekannter cluster der datei
return 1;
}
#if (WRITE==1) // anlegen ist schreiben !
else { /** Datei existiert nicht, also anlegen ! (nur wenn schreiben option an ist)**/
fat_getFreeClustersInRow(2); // leere cluster suchen, ab cluster 2.
strcpy((char *) file.name, (char *) name); // --- füllen des file struct, zum abschließenden schreiben.
file.firstCluster = fat_secToClust(fat.startSectors); // 1. cluster der datei
file.lastCluster = file.firstCluster; // fat_secToClust(fat.endSectors); // letzter bekannter cluster der datei
file.attrib = 32; // --- file.row wird in der funktion fat_getFreeRowOfDir geschrieben !!
file.length = 0; // damit da nix drin steht ^^
fat_makeFileEntry((char *) file.name, file.attrib, 0); // DATEI ANLEGEN auf karte
fat.currentSectorNr = fat_clustToSec(file.firstCluster); // setzen des ersten sektors
return 2;
}
#endif
}
//*******************************************************************************************************************************
// *******************************************************************************************************************************
// schließt die datei operation ab. eigentlich nur nötig wenn geschrieben wurde. es gibt 2 möglichkeiten :
// 1. die datei wird geschlossen und es wurde über die alte datei länge hinaus geschrieben.
// 2. die datei wird geschlossen und man war innerhalb der datei größe, dann muss nur der aktuelle sektor geschrieben werden.
// der erste fall ist komplizierter, weil ermittelt werden muss wie viele sektoren neu beschrieben wurden um diese zu verketten
// und die neue datei länge muss ermitt weden. abschließend wird entweder (fall 2) nur der aktuelle sektor geschrieben, oder
// der aktuallisierte datei eintrag und die cluster (diese werden verkettet, siehe fileUpdate() ).
//*******************************************************************************************************************************
unsigned char ffclose(void){
// *******************************************************************************************************************************
unsigned char ffclose(void)
{
#if (WRITE==1) /** 2 möglichkeiten beim schließen !! (lesend spielt keine rolle, nichts muss geupdatet werden) **/
#if (WRITE==1) /** 2 möglichkeiten beim schließen !! (lesend spielt keine rolle, nichts muss geupdatet werden) **/
if( file.length < (file.seek+file.cntOfBytes) ) fileUpdate(); /** 1.) es wurde über die alte datei größe hinaus geschrieben **/
if (file.length < (file.seek + file.cntOfBytes))
fileUpdate(); /** 1.) es wurde über die alte datei größe hinaus geschrieben **/
else if( fat.bufferDirty==1) fat_writeSector( fat.currentSectorNr ); /** 2.) nicht über alte datei länge hinaus **/
else if (fat.bufferDirty == 1)
fat_writeSector(fat.currentSectorNr); /** 2.) nicht über alte datei länge hinaus **/
#endif
file.cntOfBytes=0; // init werte der nötigen zähler
file.seek=0;
return(0);
#endif
file.cntOfBytes = 0; // init werte der nötigen zähler
file.seek = 0;
return (0);
}
// *******************************************************************************************************************************
@ -72,22 +75,24 @@ unsigned char ffclose(void){
// füllt den aktuell beschriebenen sektor mit 0x00, da sonst die datei nicht richtig angezeigt wird.
// darf nur während schreibe operationen aufgerufen werden !
// *******************************************************************************************************************************
void fileUpdate(void){
void fileUpdate(void)
{
unsigned int comp_cntOfBytes=file.cntOfBytes; // sicher nötig wegen schleife...
while( comp_cntOfBytes < 512 ){ // sektor ist beschrieben worden, daher nötigenfalls mit 00 füllen
fat.sector[comp_cntOfBytes]=0x00; // beschreibt ungenutzte bytes mit 0x00
comp_cntOfBytes++;
}
char name[13]; // zum sichern des dateinamens
unsigned long int save_length = file.cntOfBytes + file.seek; // muss gesichert werden, wird sonst von der karte geladen und verändert !
strcpy(name,(char *)file.name); // muss gesichert werden, wird sonst von der karte geladen und verändert !
fat_setClusterChain(fat_secToClust(fat.startSectors),fat_secToClust(fat.currentSectorNr)); // verketten der geschriebenen cluster
fat_loadFileDataFromDir(name); // läd sektor, des datei eintrags, und läd daten von karte auf struct file!
fat_makeRowDataEntry(file.row,name,32,file.firstCluster,save_length); // macht eintrag im puffer
unsigned int comp_cntOfBytes = file.cntOfBytes; // sicher nötig wegen schleife...
while (comp_cntOfBytes < 512) { // sektor ist beschrieben worden, daher nötigenfalls mit 00 füllen
fat.sector[comp_cntOfBytes] = 0x00; // beschreibt ungenutzte bytes mit 0x00
comp_cntOfBytes++;
}
char name[13]; // zum sichern des dateinamens
unsigned long int save_length = file.cntOfBytes + file.seek; // muss gesichert werden, wird sonst von der karte geladen und
// verändert !
strcpy(name, (char *) file.name); // muss gesichert werden, wird sonst von der karte geladen und verändert !
fat_writeSector(fat.currentSectorNr);
fat_setClusterChain(fat_secToClust(fat.startSectors), fat_secToClust(fat.currentSectorNr)); // verketten der geschriebenen cluster
fat_loadFileDataFromDir(name); // läd sektor, des datei eintrags, und läd daten von karte auf struct file!
fat_makeRowDataEntry(file.row, name, 32, file.firstCluster, save_length); // macht eintrag im puffer
fat_writeSector(fat.currentSectorNr);
}
@ -96,28 +101,30 @@ void fileUpdate(void){
// ist, dann wird der sektor geladen und der zähler für die bytes eines sektors gesetzt. wenn das byte nicht in den sektoren ist,
// die "vorgesucht" wurden, müssen noch weitere sektoren der datei gesucht werden (sec > fat.endSectors).
// *******************************************************************************************************************************
void ffseek(unsigned long int offset){
#if (OVER_WRITE==1) // man muss den dateieintrag updaten, um die daten zu retten !!
if( file.seek > file.length ) fileUpdate(); // fat verketten und datei update auf der karte !
#endif
void ffseek(unsigned long int offset)
{
fat_getFatChainClustersInRow(file.firstCluster); // suchen von anfang der cluster chain aus !
unsigned long int sec=fat.startSectors; // sektor variable zum durchgehen durch die sektoren
file.seek=0; // weil auch von anfang an der chain gesucht wird mit 0 initialisiert
#if (OVER_WRITE==1) // man muss den dateieintrag updaten, um die daten zu retten !!
if (file.seek > file.length)
fileUpdate(); // fat verketten und datei update auf der karte !
#endif
while(offset>=512){ /** suchen des sektors in dem offset ist **/
sec++; // da byte nicht in diesem sektor ist, muss hochgezählt werden
offset-=512; // ein sektor weniger in dem das byte sein kann
file.seek+=512; // file.seek update, damit bei ffclose() die richtige file.length herauskommt
if ( sec > fat.endSectors ){ // es müssen mehr sektoren der datei gesucht werden
fat_getFatChainClustersInRow(fat_getNextCluster( file.lastCluster ) ); // nachladen von clustern in der chain
sec=fat.startSectors; // setzen des 1. sektors der neu geladenen, zum weitersuchen !
}
}
file.lastCluster=fat_secToClust(fat.endSectors); // letzter bekannter cluster der datei
fat_loadSector(sec); // sektor mit offset byte laden
file.cntOfBytes = offset; // setzen des lese zählers
fat_getFatChainClustersInRow(file.firstCluster); // suchen von anfang der cluster chain aus !
unsigned long int sec = fat.startSectors; // sektor variable zum durchgehen durch die sektoren
file.seek = 0; // weil auch von anfang an der chain gesucht wird mit 0 initialisiert
while (offset >= 512) { /** suchen des sektors in dem offset ist **/
sec++; // da byte nicht in diesem sektor ist, muss hochgezählt werden
offset -= 512; // ein sektor weniger in dem das byte sein kann
file.seek += 512; // file.seek update, damit bei ffclose() die richtige file.length herauskommt
if (sec > fat.endSectors) { // es müssen mehr sektoren der datei gesucht werden
fat_getFatChainClustersInRow(fat_getNextCluster(file.lastCluster)); // nachladen von clustern in der chain
sec = fat.startSectors; // setzen des 1. sektors der neu geladenen, zum weitersuchen !
}
}
file.lastCluster = fat_secToClust(fat.endSectors); // letzter bekannter cluster der datei
fat_loadSector(sec); // sektor mit offset byte laden
file.cntOfBytes = offset; // setzen des lese zählers
}
@ -129,8 +136,9 @@ void ffseek(unsigned long int offset){
// wechselt verzeichniss. start immer im root Dir.
// MUSS in das direktory gewechselt werden, in dem die datei zum lesen/schreiben ist !
// *******************************************************************************************************************************
unsigned char ffcd(char name[]){
return(fat_cd(name));
unsigned char ffcd(char name[])
{
return (fat_cd(name));
}
@ -140,19 +148,21 @@ unsigned char ffcd(char name[]){
// eintrag in der reihe ist (nicht gelöscht, nicht frei usw). die sektoren des clusters werden nachgeladen.
// die dateien werden mit namen und datei größe angezeigt.
// *******************************************************************************************************************************
void lsRowsOfClust (unsigned long int start_sec){
void lsRowsOfClust(unsigned long int start_sec)
{
unsigned char row; // reihen
unsigned char sec=0; // sektoren
do{
fat_loadSector(start_sec + sec); // sektoren des clusters laden
for(row=0;row<16;row++){ // geht durch reihen des sektors
fat_loadRowOfSector(row); // reihe eines sektors (auf dem puffer) laden
if( (file.attrib==0x20||file.attrib==0x10) && (file.name[0]!=0xE5 && file.name[0]!=0x00) ){
printf("Name:%s Size:%li\n",file.name,file.length );
}
}
}while(++sec<fat.secPerClust);
unsigned char row; // reihen
unsigned char sec = 0; // sektoren
do {
fat_loadSector(start_sec + sec); // sektoren des clusters laden
for (row = 0; row < 16; row++) { // geht durch reihen des sektors
fat_loadRowOfSector(row); // reihe eines sektors (auf dem puffer) laden
if ((file.attrib == 0x20 || file.attrib == 0x10)
&& (file.name[0] != 0xE5 && file.name[0] != 0x00)) {
printf("Name:%s Size:%li\n", file.name, file.length);
}
}
} while (++sec < fat.secPerClust);
}
@ -161,47 +171,55 @@ void lsRowsOfClust (unsigned long int start_sec){
// unterscheidung ob man sich im rootDir befindet nötig, weil bei fat16 im root dir eine bestimmt anzahl sektoren durchsucht
// werden müssen und bei fat32 ab einem start cluster ! ruft lsRowsOfClust auf um cluster/sektoren anzuzeigen.
// *******************************************************************************************************************************
void ffls(void){
void ffls(void)
{
unsigned long int clust; // cluster
unsigned int s; // fat16 root dir sektoren
unsigned long int clust; // cluster
unsigned int s; // fat16 root dir sektoren
if(fat.dir==0 && fat.fatType==16){ // IM ROOTDIR. fat16
for(s=0;s<(unsigned int)(fat.dataDirSec+2-fat.rootDir);s++){ // zählt durch RootDir sektoren (errechnet anzahl rootDir sektoren).
lsRowsOfClust(fat.rootDir+s); // zeigt reihen eines root dir clust an
}
}
if (fat.dir == 0 && fat.fatType == 16) { // IM ROOTDIR. fat16
for (s = 0; s < (unsigned int) (fat.dataDirSec + 2 - fat.rootDir); s++) { // zählt durch RootDir sektoren (errechnet anzahl
// rootDir sektoren).
lsRowsOfClust(fat.rootDir + s); // zeigt reihen eines root dir clust an
}
}
else {
if(fat.dir==0 && fat.fatType==32)clust=fat.rootDir; // IM ROOTDIR. fat32
else clust=fat.dir; // NICHT ROOT DIR
while( !((clust==0xfffffff&&fat.fatType==32)||(clust==0xffff&&fat.fatType==16)) ){ // prüft ob weitere sektoren zum lesen da sind (fat32||fat16)
lsRowsOfClust(fat_clustToSec(clust)); // zeigt reihen des clusters an
clust=fat_getNextCluster(clust); // liest nächsten cluster des dir-eintrags
}
}
else {
if (fat.dir == 0 && fat.fatType == 32)
clust = fat.rootDir; // IM ROOTDIR. fat32
else
clust = fat.dir; // NICHT ROOT DIR
while (!((clust == 0xfffffff && fat.fatType == 32) || (clust == 0xffff && fat.fatType == 16))) { // prüft ob weitere
// sektoren zum lesen da
// sind (fat32||fat16)
lsRowsOfClust(fat_clustToSec(clust)); // zeigt reihen des clusters an
clust = fat_getNextCluster(clust); // liest nächsten cluster des dir-eintrags
}
}
}
//*******************************************************************************************************************************
// *******************************************************************************************************************************
// wechselt in das parent verzeichniss (ein verzeichniss zurück !)
// die variable fat.dir enthält den start cluster des direktory in dem man sich grade befindet, anhand diesem,
// kann der "." bzw ".." eintrag im ersten sektor des direktory ausgelesen und das parent direktory bestimmt werden.
//*******************************************************************************************************************************
unsigned char ffcdLower(void){
// *******************************************************************************************************************************
unsigned char ffcdLower(void)
{
if(fat.dir==0)return(1); // im root dir, man kann nicht höher !
if (fat.dir == 0)
return (1); // im root dir, man kann nicht höher !
fat_loadSector(fat_clustToSec(fat.dir)); // läd 1. sektor des aktuellen direktory.
fat_loadRowOfSector(1); // ".." eintrag (parent dir) ist 0 wenn parent == root
fat.dir=file.firstCluster; // dir setzen
return(0);
fat_loadSector(fat_clustToSec(fat.dir)); // läd 1. sektor des aktuellen direktory.
fat_loadRowOfSector(1); // ".." eintrag (parent dir) ist 0 wenn parent == root
fat.dir = file.firstCluster; // dir setzen
return (0);
}
#ifndef __AVR_ATmega8__
#ifndef __AVR_ATmega8__
// *******************************************************************************************************************************
// erstellt einen dir eintrag im aktuellen verzeichniss.
@ -211,236 +229,251 @@ unsigned char ffcdLower(void){
// der "." hat den 1. cluster des eigenen dirs. der ".." eintrag ist der 1. cluster des parent dirs.
// ein dir wird immer mit 0x00 initialisiert ! also alle einträge der sektoren des clusters ( bis auf . und .. einträge)!
// *******************************************************************************************************************************
void ffmkdir(char name[]){
void ffmkdir(char name[])
{
unsigned char i;
unsigned int j;
unsigned char i;
unsigned int j;
if(0==fat_loadFileDataFromDir(name))return ; // prüft ob dirname im dir schon vorhanden, wenn ja, abbruch !
if (0 == fat_loadFileDataFromDir(name))
return; // prüft ob dirname im dir schon vorhanden, wenn ja, abbruch !
// cluster in fat setzen, und ordner eintrg im aktuellen verzeichniss machen.
fat_getFreeClustersInRow(2); // holt neue freie cluster, ab cluster 2 ...
fat_setCluster(fat_secToClust(fat.startSectors),0x0fffffff); // fat16/32 cluster chain ende setzen. (neuer ordner in fat)
file.firstCluster=fat_secToClust(fat.startSectors); // dammit fat_makeFileEntry den cluster richtig setzen kann
fat_makeFileEntry(name,0x10,0); // macht dir eintrag im aktuellen verzeichniss (legt ordner im partent verzeichniss an)
// cluster in fat setzen, und ordner eintrg im aktuellen verzeichniss machen.
fat_getFreeClustersInRow(2); // holt neue freie cluster, ab cluster 2 ...
fat_setCluster(fat_secToClust(fat.startSectors), 0x0fffffff); // fat16/32 cluster chain ende setzen. (neuer ordner in fat)
file.firstCluster = fat_secToClust(fat.startSectors); // dammit fat_makeFileEntry den cluster richtig setzen kann
fat_makeFileEntry(name, 0x10, 0); // macht dir eintrag im aktuellen verzeichniss (legt ordner im partent verzeichniss an)
// aufbereiten des puffers
j=511;
do{
fat.sector[j]=0x00; //schreibt puffer fat.sector voll mit 0x00==leer
}while(j--);
// aufbereiten des puffers
j = 511;
do {
fat.sector[j] = 0x00; // schreibt puffer fat.sector voll mit 0x00==leer
} while (j--);
// aufbereiten des clusters
for(i=1;i<fat.secPerClust;i++){ // ein dir cluster muss mit 0x00 initialisiert werden !
fat_writeSector(fat.startSectors+i); // löschen des cluster (überschreibt mit 0x00), wichtig bei ffls!
}
// aufbereiten des clusters
for (i = 1; i < fat.secPerClust; i++) { // ein dir cluster muss mit 0x00 initialisiert werden !
fat_writeSector(fat.startSectors + i); // löschen des cluster (überschreibt mit 0x00), wichtig bei ffls!
}
// aufbereiten des neuen dir sektors mit "." und ".." eintraegen !
fat_makeRowDataEntry(0,". ",0x10,file.firstCluster,0); // macht "." eintrag des dirs
fat_makeRowDataEntry(1,".. ",0x10,fat.dir,0); // macht ".." eintrag des dirs
fat_writeSector(fat_clustToSec(file.firstCluster)); // schreibt einträge auf karte !
// aufbereiten des neuen dir sektors mit "." und ".." eintraegen !
fat_makeRowDataEntry(0, ". ", 0x10, file.firstCluster, 0); // macht "." eintrag des dirs
fat_makeRowDataEntry(1, ".. ", 0x10, fat.dir, 0); // macht ".." eintrag des dirs
fat_writeSector(fat_clustToSec(file.firstCluster)); // schreibt einträge auf karte !
}
#endif // ffmkdir wegen atmega8
#endif // ffmkdir wegen atmega8
#endif
#if (WRITE==1)
//*******************************************************************************************************************************
// *******************************************************************************************************************************
// löscht datei/ordner aus aktuellem verzeichniss, wenn es die datei gibt.
// löscht dateien und ordner rekursiv !
//*******************************************************************************************************************************
unsigned char ffrm(char name[]){
// *******************************************************************************************************************************
unsigned char ffrm(char name[])
{
if(0==fat_loadFileDataFromDir(name)){ // datei oder ordner ist vorhanden, nur dann lösch operation
if (0 == fat_loadFileDataFromDir(name)) { // datei oder ordner ist vorhanden, nur dann lösch operation
if(file.attrib!=0x10){ // ist datei.
fat.sector[file.row<<5]=0xE5; // datei gelöscht markieren (file.row*32, damit man auf reihen anfang kommt)
if((file.row-1)>=0){ // gibt es einen eintrag davor ?
if(fat.sector[(file.row<<5)-21]==0x0f)fat.sector[(file.row<<5)-32]=0xE5; // langer datei eintag auch gelöscht.
}
fat.bufferDirty=1; // eintrag in puffer gemacht.
if(0==fat_getNextCluster(file.firstCluster)) return(0); // 1.cluster ist leer ?!?
fat_delClusterChain(file.firstCluster); // löscht die zu der datei gehörige cluster-chain aus der fat.
return(0);
}
//TODO noch nicht optimal. zu viele schreib vorgänge beim löschen von datei einträgen. max bis zu 16/sektor !
else{ // ist ordner, dann rekursiv löschen !!
#ifndef __AVR_ATmega8__ // mega8 zu klein für die funktionalität....
unsigned long int parent;
unsigned long int own;
unsigned long int clustsOfDir; // um durch die cluster chain eines dirs zu gehen.
unsigned char cntSecOfClust=0;
unsigned char i=0;
if (file.attrib != 0x10) { // ist datei.
fat.sector[file.row << 5] = 0xE5; // datei gelöscht markieren (file.row*32, damit man auf reihen anfang kommt)
if ((file.row - 1) >= 0) { // gibt es einen eintrag davor ?
if (fat.sector[(file.row << 5) - 21] == 0x0f)
fat.sector[(file.row << 5) - 32] = 0xE5; // langer datei eintag auch gelöscht.
}
fat.bufferDirty = 1; // eintrag in puffer gemacht.
if (0 == fat_getNextCluster(file.firstCluster))
return (0); // 1.cluster ist leer ?!?
fat_delClusterChain(file.firstCluster); // löscht die zu der datei gehörige cluster-chain aus der fat.
return (0);
}
// TODO noch nicht optimal. zu viele schreib vorgänge beim löschen von datei einträgen. max bis zu 16/sektor !
else { // ist ordner, dann rekursiv löschen !!
#ifndef __AVR_ATmega8__ // mega8 zu klein für die funktionalität....
unsigned long int parent;
unsigned long int own;
unsigned long int clustsOfDir; // um durch die cluster chain eines dirs zu gehen.
unsigned char cntSecOfClust = 0;
unsigned char i = 0;
fat.sector[file.row<<5]=0xE5; // löscht dir eintrag
if((file.row-1)>=0){ // gibt es einen eintrag davor (langer datei eintrag)?
if(fat.sector[(file.row<<5)-21]==0x0f)fat.sector[(file.row<<5)-32]=0xE5; // langer datei eintag auch gelöscht
}
fat.bufferDirty=1; // puffer eintrag gemacht
fat.sector[file.row << 5] = 0xE5; // löscht dir eintrag
if ((file.row - 1) >= 0) { // gibt es einen eintrag davor (langer datei eintrag)?
if (fat.sector[(file.row << 5) - 21] == 0x0f)
fat.sector[(file.row << 5) - 32] = 0xE5; // langer datei eintag auch gelöscht
}
fat.bufferDirty = 1; // puffer eintrag gemacht
parent=fat.dir; // der ordner in dem der zu löschende ordner ist.
own=file.firstCluster; // der 1. cluster des ordners der zu löschen ist.
clustsOfDir=file.firstCluster; // die "cluster" des zu löschenden ordners
parent = fat.dir; // der ordner in dem der zu löschende ordner ist.
own = file.firstCluster; // der 1. cluster des ordners der zu löschen ist.
clustsOfDir = file.firstCluster; // die "cluster" des zu löschenden ordners
do{ // geht durch cluster des dirs
fat_loadSector(fat_clustToSec(clustsOfDir)); // sektor des dirs laden
do{ // geht durch sektoren des clusters
do{ // geht durch reihen des sektors
fat_loadRowOfSector(i);
do { // geht durch cluster des dirs
fat_loadSector(fat_clustToSec(clustsOfDir)); // sektor des dirs laden
do { // geht durch sektoren des clusters
do { // geht durch reihen des sektors
fat_loadRowOfSector(i);
if(file.attrib!=0x10 && file.attrib!=0x00 && file.name[0]!=0xE5){ // ist kein ordner,noch nicht gelöscht, kein freier eintrag
fat.sector[i<<5]=0xE5; // erster eintrag der reihe als gelöscht markiert
fat.bufferDirty=1; // puffer eintrag gemacht
if(file.attrib==0x20){ // ist datei!
fat_delClusterChain(file.firstCluster); // ist datei, dann cluster-chain der datei löschen
fat_loadSector(fat_clustToSec(clustsOfDir)+cntSecOfClust); // sektor neu laden, weil löschen der chain, den puffer nutzt.
}
}
if (file.attrib != 0x10 && file.attrib != 0x00 && file.name[0] != 0xE5) { // ist kein ordner,noch nicht
// gelöscht, kein freier eintrag
fat.sector[i << 5] = 0xE5; // erster eintrag der reihe als gelöscht markiert
fat.bufferDirty = 1; // puffer eintrag gemacht
if (file.attrib == 0x20) { // ist datei!
fat_delClusterChain(file.firstCluster); // ist datei, dann cluster-chain der datei löschen
fat_loadSector(fat_clustToSec(clustsOfDir) + cntSecOfClust); // sektor neu laden, weil löschen der
// chain, den puffer nutzt.
}
}
if(file.attrib==0x10 && file.name[0]=='.'){ // "." oder ".." eintrag erkannt, löschen !
fat.sector[i<<5]=0xE5; // eintrag als gelöscht markiert
fat.bufferDirty=1; // puffer eintrag gemacht
}
if (file.attrib == 0x10 && file.name[0] == '.') { // "." oder ".." eintrag erkannt, löschen !
fat.sector[i << 5] = 0xE5; // eintrag als gelöscht markiert
fat.bufferDirty = 1; // puffer eintrag gemacht
}
if(file.attrib==0x10 && file.name[0]!='.' && file.name[0]!=0xE5 && file.name[0]!=0){ // ordner erkannt !
fat.sector[i<<5]=0xE5; // dir eintrag als gelöscht markiert
fat.bufferDirty=1; // puffer eintrag gemacht
fat_loadSector(fat_clustToSec(file.firstCluster)); // sektor des dirs laden
clustsOfDir=file.firstCluster; // eigenes dir ist file.firstCluster
own=file.firstCluster; // eigener start cluster/dir
fat_loadRowOfSector(1); // ".." laden um parent zu bestimmen
parent=file.firstCluster; // parent sichern.
cntSecOfClust=0; // init von gelesenen sektoren und reihen !
i=0;
continue;
}
if (file.attrib == 0x10 && file.name[0] != '.' && file.name[0] != 0xE5 && file.name[0] != 0) { // ordner erkannt !
fat.sector[i << 5] = 0xE5; // dir eintrag als gelöscht markiert
fat.bufferDirty = 1; // puffer eintrag gemacht
fat_loadSector(fat_clustToSec(file.firstCluster)); // sektor des dirs laden
clustsOfDir = file.firstCluster; // eigenes dir ist file.firstCluster
own = file.firstCluster; // eigener start cluster/dir
fat_loadRowOfSector(1); // ".." laden um parent zu bestimmen
parent = file.firstCluster; // parent sichern.
cntSecOfClust = 0; // init von gelesenen sektoren und reihen !
i = 0;
continue;
}
if(file.name[0]==0x00){ // ende des dirs erreicht, wenn nicht voll !!
if(parent==fat.dir){ // erfolgreich alles gelöscht
fat_delClusterChain(own); // cluster chain des ordners löschen
return(0);
}
fat_delClusterChain(own); // cluster chain des ordners löschen
clustsOfDir=parent; // parent ist jetzt wieder arbeisverzeichniss.
own=parent; // arbeitsverzeichniss setzten
fat_loadSector(fat_clustToSec(own)); // sektor des dirs laden
fat_loadRowOfSector(1); // ".." laden um parent zu bestimmen
parent=file.firstCluster; // parent sichern.
cntSecOfClust=0; // init von gelesenen sektoren und reihen !
i=0;
continue;
}
if (file.name[0] == 0x00) { // ende des dirs erreicht, wenn nicht voll !!
if (parent == fat.dir) { // erfolgreich alles gelöscht
fat_delClusterChain(own); // cluster chain des ordners löschen
return (0);
}
fat_delClusterChain(own); // cluster chain des ordners löschen
clustsOfDir = parent; // parent ist jetzt wieder arbeisverzeichniss.
own = parent; // arbeitsverzeichniss setzten
fat_loadSector(fat_clustToSec(own)); // sektor des dirs laden
fat_loadRowOfSector(1); // ".." laden um parent zu bestimmen
parent = file.firstCluster; // parent sichern.
cntSecOfClust = 0; // init von gelesenen sektoren und reihen !
i = 0;
continue;
}
i++;
}while(i<16); // geht durch reihen des sektors.
i=0; // neuer sektor -> reihen von vorne.
cntSecOfClust++;
fat_loadSector(fat_clustToSec(clustsOfDir)+cntSecOfClust); // läd sektoren des clusters nach
}while(cntSecOfClust<fat.secPerClust); // geht durch sektoren des clusters.
cntSecOfClust=0; // neuer cluster -> sektoren von vorne.
clustsOfDir=fat_getNextCluster(clustsOfDir); // sucht neuen cluster der cluster-chain.
}while( !((clustsOfDir==0xfffffff && fat.fatType==32) || (clustsOfDir==0xffff && fat.fatType==16)) ); // geht durch cluster des dirs.
fat_delClusterChain(own); // hier landet man, wenn der ordner voll war (auf cluster "ebene")!!
#endif
}
}
i++;
} while (i < 16); // geht durch reihen des sektors.
return(1); // fehler, nicht gefunden?
i = 0; // neuer sektor -> reihen von vorne.
cntSecOfClust++;
fat_loadSector(fat_clustToSec(clustsOfDir) + cntSecOfClust); // läd sektoren des clusters nach
} while (cntSecOfClust < fat.secPerClust); // geht durch sektoren des clusters.
cntSecOfClust = 0; // neuer cluster -> sektoren von vorne.
clustsOfDir = fat_getNextCluster(clustsOfDir); // sucht neuen cluster der cluster-chain.
} while (!((clustsOfDir == 0xfffffff && fat.fatType == 32) || (clustsOfDir == 0xffff && fat.fatType == 16))); // geht
// durch
// cluster
// des
// dirs.
fat_delClusterChain(own); // hier landet man, wenn der ordner voll war (auf cluster "ebene")!!
#endif
}
}
return (1); // fehler, nicht gefunden?
}
#endif
//*******************************************************************************************************************************
// *******************************************************************************************************************************
// liest 512 bytes aus dem puffer fat.sector. dann werden neue 512 bytes der datei geladen, sind nicht genügend verkettete
// sektoren in einer reihe bekannt, wird in der fat nachgeschaut. dann werden weiter bekannte nachgeladen...
//*******************************************************************************************************************************
inline unsigned char ffread(void){
// *******************************************************************************************************************************
inline unsigned char ffread(void)
{
if(file.cntOfBytes==512){ /** EINEN SEKTOR GLESEN (ab hier 2 möglichkeiten !) **/
file.cntOfBytes=0; // byte zähler zurück setzen
if( fat.currentSectorNr == fat.endSectors ){ /** 1.) nötig mehr sektoren der chain zu laden (mit ein bisschen glück nur alle 512*MAX_CLUSTERS_IN_ROW bytes)**/
fat_getFatChainClustersInRow(fat_getNextCluster(fat_secToClust( fat.endSectors) )); // nachladen von clustern in der chain
fat.currentSectorNr=fat.startSectors-1; // setzen des nächsten sektors um weiter lesen zu können..
}
fat_loadSector(fat.currentSectorNr+1); /** 2.) die bekannten in einer reihe reichen noch.(nur alle 512 bytes)**/
}
return fat.sector[file.cntOfBytes++]; // rückgabe, byte des sektors (NACH rückgabe erhöhen von zähler ! )
if (file.cntOfBytes == 512) { /** EINEN SEKTOR GLESEN (ab hier 2 möglichkeiten !) **/
file.cntOfBytes = 0; // byte zähler zurück setzen
if (fat.currentSectorNr == fat.endSectors) { /** 1.) nötig mehr sektoren der chain zu laden (mit ein bisschen glück nur alle 512*MAX_CLUSTERS_IN_ROW bytes)**/
fat_getFatChainClustersInRow(fat_getNextCluster(fat_secToClust(fat.endSectors))); // nachladen von clustern in der chain
fat.currentSectorNr = fat.startSectors - 1; // setzen des nächsten sektors um weiter lesen zu können..
}
fat_loadSector(fat.currentSectorNr + 1); /** 2.) die bekannten in einer reihe reichen noch.(nur alle 512 bytes)**/
}
return fat.sector[file.cntOfBytes++]; // rückgabe, byte des sektors (NACH rückgabe erhöhen von zähler ! )
}
#if (WRITE==1)
#if (OVER_WRITE==0) // nicht überschreibende write funktion
#if (OVER_WRITE==0) // nicht überschreibende write funktion
//*******************************************************************************************************************************
// *******************************************************************************************************************************
// schreibt 512 byte blöcke auf den puffer fat.sector. dann wird dieser auf die karte geschrieben. wenn genügend feie
// sektoren zum beschreiben bekannt sind(datenmenge zu groß), muss nicht in der fat nachgeschaut werden. sollten nicht genügend
// zusammenhängende sektoren bekannt sein, werden die alten verkettet und neue gesucht. es ist nötig sich den letzten bekannten
// einer kette zu merken -> file.lastCluster, um auch nicht zusammenhängende cluster verketten zu können (fat_setClusterChain macht das)!
//*******************************************************************************************************************************
inline void ffwrite(unsigned char c){
fat.sector[file.cntOfBytes++]=c; // schreiben des chars auf den puffer sector und zähler erhöhen (pre-increment)
fat.bufferDirty=1; // puffer dirty weil geschrieben und noch nicht auf karte.
// *******************************************************************************************************************************
inline void ffwrite(unsigned char c)
{
if( file.cntOfBytes==512 ){ /** SEKTOR VOLL ( 2 möglichkeiten ab hier !) **/
file.cntOfBytes=0; // rücksetzen des sektor byte zählers
mmc_write_sector(fat.currentSectorNr,fat.sector); /** 1.) vollen sektor auf karte schreiben **/
fat.bufferDirty=0; // puffer jetzt clear, weil grade alles geschrieben.
file.seek+=512; // position in der datei erhöhen, weil grade 512 bytes geschrieben
if( fat.currentSectorNr==fat.endSectors ){ /** 2.) es ist nötig, neue freie zu suchen und die alten zu verketten (mit ein bischen glück nur alle 512*MAX_CLUSTERS_IN_ROW bytes) **/
fat_setClusterChain( fat_secToClust(fat.startSectors) , fat_secToClust(fat.endSectors) ); // verketten der beschriebenen
fat_getFreeClustersInRow(file.lastCluster); // suchen von leeren sektoren.
fat.currentSectorNr=fat.startSectors-1; // setzen des 1. sektors der neuen reihe zum schreiben.
}
fat.currentSectorNr++; // nächsten sektor zum beschreiben.
}
fat.sector[file.cntOfBytes++] = c; // schreiben des chars auf den puffer sector und zähler erhöhen (pre-increment)
fat.bufferDirty = 1; // puffer dirty weil geschrieben und noch nicht auf karte.
if (file.cntOfBytes == 512) { /** SEKTOR VOLL ( 2 möglichkeiten ab hier !) **/
file.cntOfBytes = 0; // rücksetzen des sektor byte zählers
mmc_write_sector(fat.currentSectorNr, fat.sector); /** 1.) vollen sektor auf karte schreiben **/
fat.bufferDirty = 0; // puffer jetzt clear, weil grade alles geschrieben.
file.seek += 512; // position in der datei erhöhen, weil grade 512 bytes geschrieben
if (fat.currentSectorNr == fat.endSectors) { /** 2.) es ist nötig, neue freie zu suchen und die alten zu verketten (mit ein bischen glück nur alle 512*MAX_CLUSTERS_IN_ROW bytes) **/
fat_setClusterChain(fat_secToClust(fat.startSectors), fat_secToClust(fat.endSectors)); // verketten der beschriebenen
fat_getFreeClustersInRow(file.lastCluster); // suchen von leeren sektoren.
fat.currentSectorNr = fat.startSectors - 1; // setzen des 1. sektors der neuen reihe zum schreiben.
}
fat.currentSectorNr++; // nächsten sektor zum beschreiben.
}
}
#endif
#if (OVER_WRITE==1) // überschreibende write funktion, nicht performant, weil immer auch noch ein sektor geladen werden muss
#if (OVER_WRITE==1) // überschreibende write funktion, nicht performant, weil immer auch noch ein sektor geladen werden muss
//*******************************************************************************************************************************
// *******************************************************************************************************************************
// schreibt 512 byte blöcke auf den puffer fat.sector. dann wird dieser auf die karte geschrieben. wenn genügend feie
// sektoren zum beschreiben bekannt sind, muss nicht in der fat nachgeschaut werden. sollten nicht genügend zusammenhängende
// sektoren bekannt sein(datenmenge zu groß), werden die alten verkettet und neue gesucht. es ist nötig sich den letzten bekannten einer
// kette zu merken -> file.lastCluster, um auch nicht zusammenhängende cluster verketten zu können (fat_setClusterChain macht das)!
// es ist beim überschreiben nötig, die schon beschriebenen sektoren der datei zu laden, damit man die richtigen daten
// hat. das ist blöd, weil so ein daten overhead von 50% entsteht. da lesen aber schneller als schreiben geht, verliert man nicht 50% an geschwindigkeit.
//*******************************************************************************************************************************
inline void ffwrite(unsigned char c){
fat.sector[file.cntOfBytes++]=c; // schreiben des chars auf den puffer sector und zähler erhöhen (pre-increment)
fat.bufferDirty=1; // puffer dirty weil geschrieben und noch nicht auf karte.
// hat. das ist blöd, weil so ein daten overhead von 50% entsteht. da lesen aber schneller als schreiben geht, verliert man nicht 50% an
// geschwindigkeit.
// *******************************************************************************************************************************
inline void ffwrite(unsigned char c)
{
if( file.cntOfBytes==512 ){ /** SEKTOR VOLL ( 2 möglichkeiten ab hier !) **/
file.cntOfBytes=0; // rücksetzen des sektor byte zählers.
mmc_write_sector(fat.currentSectorNr,fat.sector); /** 1.) vollen sektor auf karte schreiben**/
fat.bufferDirty=0; // puffer jetzt clear, weil grade alles geschrieben.
file.seek+=512; // position in der datei erhöhen, weil grade 512 bytes geschrieben.
if( fat.currentSectorNr==fat.endSectors ){ /** 2.) es ist nötig, neue freie zu suchen und die alten zu verketten (mit ein bischen glück nur alle 512*MAX_CLUSTERS_IN_ROW bytes) **/
if( file.seek > file.length ){ // außerhalb der datei !!
fat_setClusterChain( fat_secToClust(fat.startSectors) , fat_secToClust(fat.endSectors) ); // verketten der beschriebenen.
fat_getFreeClustersInRow( file.lastCluster ); // neue leere sektoren benötigt, also suchen.
}
else {
fat_getFatChainClustersInRow( fat_getNextCluster(file.lastCluster) ); // noch innerhalb der datei, deshlab verkettete suchen.
}
fat.currentSectorNr=fat.startSectors-1; // setzen des 1. sektors der neuen reihe zum schreiben.
}
fat.currentSectorNr++; // nächsten sektor zum beschreiben.
mmc_read_sector(fat.currentSectorNr,fat.sector); // wegen überschreiben, muss der zu beschreibende sektor geladen werden...
}
fat.sector[file.cntOfBytes++] = c; // schreiben des chars auf den puffer sector und zähler erhöhen (pre-increment)
fat.bufferDirty = 1; // puffer dirty weil geschrieben und noch nicht auf karte.
if (file.cntOfBytes == 512) { /** SEKTOR VOLL ( 2 möglichkeiten ab hier !) **/
file.cntOfBytes = 0; // rücksetzen des sektor byte zählers.
mmc_write_sector(fat.currentSectorNr, fat.sector); /** 1.) vollen sektor auf karte schreiben**/
fat.bufferDirty = 0; // puffer jetzt clear, weil grade alles geschrieben.
file.seek += 512; // position in der datei erhöhen, weil grade 512 bytes geschrieben.
if (fat.currentSectorNr == fat.endSectors) { /** 2.) es ist nötig, neue freie zu suchen und die alten zu verketten (mit ein bischen glück nur alle 512*MAX_CLUSTERS_IN_ROW bytes) **/
if (file.seek > file.length) { // außerhalb der datei !!
fat_setClusterChain(fat_secToClust(fat.startSectors), fat_secToClust(fat.endSectors)); // verketten der beschriebenen.
fat_getFreeClustersInRow(file.lastCluster); // neue leere sektoren benötigt, also suchen.
} else {
fat_getFatChainClustersInRow(fat_getNextCluster(file.lastCluster)); // noch innerhalb der datei, deshlab verkettete
// suchen.
}
fat.currentSectorNr = fat.startSectors - 1; // setzen des 1. sektors der neuen reihe zum schreiben.
}
fat.currentSectorNr++; // nächsten sektor zum beschreiben.
mmc_read_sector(fat.currentSectorNr, fat.sector); // wegen überschreiben, muss der zu beschreibende sektor geladen werden...
}
}
#endif
@ -448,16 +481,10 @@ inline void ffwrite(unsigned char c){
// *******************************************************************************************************************************
// schreibt string auf karte, siehe ffwrite()
// *******************************************************************************************************************************
inline void ffwrites(const char *s ){
while (*s) ffwrite(*s++);
}
inline void ffwrites(const char *s)
{
while (*s)
ffwrite(*s++);
}
#endif

View File

@ -3,33 +3,30 @@
#ifndef _FILE_H
#define _FILE_H
#define _FILE_H
// **************************************************************************************************************************
// funktionen
extern inline unsigned char ffread(void); // liest byte-weise aus der datei (puffert immer 512 bytes zwischen)
extern inline void ffwrite(unsigned char c); // schreibt ein byte in die geöffnete datei
extern inline void ffwrites(const char *s ); // schreibt string auf karte
extern inline unsigned char ffread(void); // liest byte-weise aus der datei (puffert immer 512 bytes zwischen)
extern inline void ffwrite(unsigned char c); // schreibt ein byte in die geöffnete datei
extern inline void ffwrites(const char *s); // schreibt string auf karte
extern unsigned char ffopen(char name[]); // kann immer nur 1 datei bearbeiten.
extern unsigned char ffclose(void); // muss aufgerufen werden bevor neue datei bearbeitet wird.
extern void ffseek(unsigned long int offset); // setzt zeiger:bytesOfSec auf position in der geöffneten datei.
extern unsigned char ffcd(char name[]); // wechselt direktory
extern void ffls(void); // zeigt direktory inhalt an
extern unsigned char ffcdLower(void); // geht ein direktory zurück, also cd.. (parent direktory)
extern unsigned char ffrm(char name[]); // löscht datei aus aktuellem verzeichniss.
extern void ffmkdir(char name[]); // legt ordner in aktuellem verzeichniss an.
void lsRowsOfClust(unsigned long int start_sec); // zeigt reihen eines clusters an, ab start_sec
void fileUpdate(void); // updatet datei eintrag auf karte
// **************************************************************************************************************************//
// #######################################################################################################################
extern unsigned char ffopen(char name[]); // kann immer nur 1 datei bearbeiten.
extern unsigned char ffclose(void); // muss aufgerufen werden bevor neue datei bearbeitet wird.
extern void ffseek(unsigned long int offset); // setzt zeiger:bytesOfSec auf position in der geöffneten datei.
extern unsigned char ffcd(char name[]); // wechselt direktory
extern void ffls(void); // zeigt direktory inhalt an
extern unsigned char ffcdLower(void); // geht ein direktory zurück, also cd.. (parent direktory)
extern unsigned char ffrm(char name[]); // löscht datei aus aktuellem verzeichniss.
extern void ffmkdir(char name[]); // legt ordner in aktuellem verzeichniss an.
void lsRowsOfClust (unsigned long int start_sec); // zeigt reihen eines clusters an, ab start_sec
void fileUpdate(void); // updatet datei eintrag auf karte
// **************************************************************************************************************************// #######################################################################################################################
#endif

View File

@ -1,32 +1,29 @@
/*#######################################################################################
Connect AVR to MMC/SD
Copyright (C) 2004 Ulrich Radig
Bei Fragen und Verbesserungen wendet euch per EMail an
mail@ulrichradig.de
oder im Forum meiner Web Page : www.ulrichradig.de
Dieses Programm ist freie Software. Sie können es unter den Bedingungen der
GNU General Public License, wie von der Free Software Foundation veröffentlicht,
weitergeben und/oder modifizieren, entweder gemäß Version 2 der Lizenz oder
(nach Ihrer Option) jeder späteren Version.
Die Veröffentlichung dieses Programms erfolgt in der Hoffnung,
daß es Ihnen von Nutzen sein wird, aber OHNE IRGENDEINE GARANTIE,
sogar ohne die implizite Garantie der MARKTREIFE oder der VERWENDBARKEIT
FÜR EINEN BESTIMMTEN ZWECK. Details finden Sie in der GNU General Public License.
Sie sollten eine Kopie der GNU General Public License zusammen mit diesem
Programm erhalten haben.
Falls nicht, schreiben Sie an die Free Software Foundation,
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
#######################################################################################*/
/*
* ####################################################################################### Connect AVR to MMC/SD
*
* Copyright (C) 2004 Ulrich Radig
*
* Bei Fragen und Verbesserungen wendet euch per EMail an
*
* mail@ulrichradig.de
*
* oder im Forum meiner Web Page : www.ulrichradig.de
*
* Dieses Programm ist freie Software. Sie können es unter den Bedingungen der GNU General Public License, wie von der Free Software
* Foundation veröffentlicht, weitergeben und/oder modifizieren, entweder gemäß Version 2 der Lizenz oder (nach Ihrer Option) jeder
* späteren Version.
*
* Die Veröffentlichung dieses Programms erfolgt in der Hoffnung, daß es Ihnen von Nutzen sein wird, aber OHNE IRGENDEINE GARANTIE,
* sogar ohne die implizite Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Details finden Sie in der GNU
* General Public License.
*
* Sie sollten eine Kopie der GNU General Public License zusammen mit diesem Programm erhalten haben. Falls nicht, schreiben Sie an die
* Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
* #######################################################################################
*/
#include <avr/io.h>
#include <util/delay.h>
#include <util/delay.h>
#include "mmc.h"
@ -46,7 +43,7 @@ uint8_t mmc_init()
_delay_us(10);
MMC_WRITE &= ~(1 << MMC_CS);
_delay_us(3);
uint8_t CMD[] = { 0x40, 0x00, 0x00, 0x00, 0x00, 0x95 };
while (mmc_write_command(CMD) != 1) {
if (Timeout++ > 20) {
@ -54,7 +51,7 @@ uint8_t mmc_init()
return (1);
}
}
Timeout = 0;
CMD[0] = 0x41;
CMD[5] = 0xFF;
@ -71,11 +68,11 @@ uint8_t mmc_write_command(uint8_t * cmd)
uint8_t tmp = 0xff;
uint16_t Timeout = 0;
uint8_t a;
for (a = 0; a < 0x06; a++) {
mmc_write_byte(*cmd++);
}
while (tmp == 0xff) {
tmp = mmc_read_byte();
if (Timeout++ > 50) {
@ -84,8 +81,8 @@ uint8_t mmc_write_command(uint8_t * cmd)
}
return (tmp);
}
uint8_t mmc_read_byte(void)
{
uint8_t Byte = 0, j;
@ -96,7 +93,7 @@ uint8_t mmc_read_byte(void)
if (PINB & (1 << MMC_DI)) {
Byte |= 1;
}
else {
Byte &= ~1;
}
@ -105,8 +102,8 @@ uint8_t mmc_read_byte(void)
}
return (Byte);
}
void mmc_write_byte(uint8_t Byte)
{
uint8_t i;
@ -114,7 +111,7 @@ void mmc_write_byte(uint8_t Byte)
if (Byte & 0x80) {
MMC_WRITE |= (1 << MMC_DO);
}
else {
MMC_WRITE &= ~(1 << MMC_DO);
}
@ -130,72 +127,72 @@ void mmc_write_byte(uint8_t Byte)
uint8_t mmc_write_sector(uint32_t addr, uint8_t * Buffer)
{
uint8_t tmp;
uint8_t cmd[] = { 0x58, 0x00, 0x00, 0x00, 0x00, 0xFF };
uint8_t a;
uint16_t i;
addr = addr << 9;
cmd[1] = ((addr & 0xFF000000) >> 24);
cmd[2] = ((addr & 0x00FF0000) >> 16);
cmd[3] = ((addr & 0x0000FF00) >> 8);
tmp = mmc_write_command(cmd);
if (tmp != 0) {
return (tmp);
}
for (a = 0; a < 100; a++) {
mmc_read_byte();
}
mmc_write_byte(0xFE);
for (a = 0; i < 512; i++) {
mmc_write_byte(*Buffer++);
}
mmc_write_byte(0xFF);
mmc_write_byte(0xFF);
if ((mmc_read_byte() & 0x1F) != 0x05)
return (1);
while (mmc_read_byte() != 0xff) {
};
return (0);
}
void mmc_read_block(uint8_t * cmd, uint8_t * Buffer, uint16_t Bytes)
{
uint16_t a;
if (mmc_write_command(cmd) != 0) {
return;
}
while (mmc_read_byte() != 0xfe) {
};
for (a = 0; a < Bytes; a++) {
*Buffer++ = mmc_read_byte();
}
mmc_read_byte();
mmc_read_byte();
return;
}
uint8_t mmc_read_sector(uint32_t addr, uint8_t * Buffer)
{
uint8_t cmd[] = { 0x51, 0x00, 0x00, 0x00, 0x00, 0xFF };
addr = addr << 9;
cmd[1] = ((addr & 0xFF000000) >> 24);
cmd[2] = ((addr & 0x00FF0000) >> 16);
@ -203,22 +200,21 @@ uint8_t mmc_read_sector(uint32_t addr, uint8_t * Buffer)
mmc_read_block(cmd, Buffer, 512);
return (0);
}
uint8_t mmc_read_cid(uint8_t * Buffer)
{
uint8_t cmd[] = { 0x4A, 0x00, 0x00, 0x00, 0x00, 0xFF };
mmc_read_block(cmd, Buffer, 16);
return (0);
}
uint8_t mmc_read_csd(uint8_t * Buffer)
{
uint8_t cmd[] = { 0x49, 0x00, 0x00, 0x00, 0x00, 0xFF };
mmc_read_block(cmd, Buffer, 16);
return (0);
}

View File

@ -1,44 +1,44 @@
/*#######################################################################################
Connect ARM to MMC/SD
Copyright (C) 2004 Ulrich Radig
#######################################################################################*/
/*
* ####################################################################################### Connect ARM to MMC/SD
*
* Copyright (C) 2004 Ulrich Radig #######################################################################################
*/
#ifndef _MMC_H
#define _MMC_H
#define _MMC_H
#define SPI_Mode 0 //1 = Hardware SPI | 0 = Software SPI
#define SPI_Mode 0 // 1 = Hardware SPI | 0 = Software SPI
#define MMC_WRITE PORTB
#define MMC_READ PINB
#define MMC_REG DDRB
#define MMC_CS PB4
#define MMC_DO PB6
#define MMC_DI PB5
#define MMC_CLK PB7
#define MMC_WRITE PORTB //Port an der die MMC/SD-Karte angeschlossen ist also des SPI
#define MMC_WRITE PORTB // Port an der die MMC/SD-Karte angeschlossen ist also des SPI
#define MMC_READ PINB
#define MMC_REG DDRB
#define MMC_REG DDRB
extern unsigned char mmc_read_byte(void);
extern void mmc_write_byte(unsigned char);
extern void mmc_read_block(unsigned char *,unsigned char *,unsigned in);
extern unsigned char mmc_init(void);
extern unsigned char mmc_read_sector (unsigned long,unsigned char *);
extern unsigned char mmc_write_sector (unsigned long,unsigned char *);
extern unsigned char mmc_write_command (unsigned char *);
#define mmc_disable() MMC_WRITE|= (1<<MMC_CS);
extern unsigned char mmc_read_byte(void);
extern void mmc_write_byte(unsigned char);
extern void mmc_read_block(unsigned char *, unsigned char *, unsigned in);
extern unsigned char mmc_init(void);
extern unsigned char mmc_read_sector(unsigned long, unsigned char *);
extern unsigned char mmc_write_sector(unsigned long, unsigned char *);
extern unsigned char mmc_write_command(unsigned char *);
#define mmc_enable() MMC_WRITE&=~(1<<MMC_CS);
#define mmc_disable() MMC_WRITE|= (1<<MMC_CS);
#define nop() __asm__ __volatile__ ("nop" ::)
#define mmc_enable() MMC_WRITE&=~(1<<MMC_CS);
#define nop() __asm__ __volatile__ ("nop" ::)
#endif

View File

@ -124,26 +124,12 @@ void test_sdcard(void){
printf("fatinit failed\n");
return;
}
printf("Root dirlist\n");
ffls();
printf("FOLDER2 dirlist\n");
ffcd("FOLDER1");
ffls();
char datei[12]="test.txt"; // hier muss platz für 11 zeichen sein (8.3), da fat_str diesen string benutzt !!
fat_str(datei);
ffrm( datei ); // löschen der datei/ordner falls vorhanden
printf("open %s\n",datei);
ffopen( datei );
printf("write %s\n",datei);
ffwrites((char*)"Hallo Datei :)");
ffwrite(0x0D);
ffwrite(0x0A);
printf("close %s\n",datei);
ffclose();
printf("open %s\n",datei);
ffopen( datei );
printf("open %s\n",datei);
unsigned long int seek=file.length; // eine variable setzen und runterzählen bis 0 geht am schnellsten !
do{
printf("%c",ffread()); // liest ein zeichen und gibt es über uart aus !
}while(--seek); // liest solange bytes da sind (von datei länge bis 0)
ffclose(); // schließt datei
}

View File

@ -2,6 +2,8 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>currentDocument</key>
<string>poc/avr_usbload/sram.c</string>
<key>documents</key>
<array>
<dict>
@ -19,7 +21,125 @@
<integer>271</integer>
<key>metaData</key>
<dict>
<key>avr/bootloader/bootloader.c</key>
<dict>
<key>caret</key>
<dict>
<key>column</key>
<integer>11</integer>
<key>line</key>
<integer>231</integer>
</dict>
<key>columnSelection</key>
<false/>
<key>firstVisibleColumn</key>
<integer>0</integer>
<key>firstVisibleLine</key>
<integer>189</integer>
<key>selectFrom</key>
<dict>
<key>column</key>
<integer>8</integer>
<key>line</key>
<integer>231</integer>
</dict>
<key>selectTo</key>
<dict>
<key>column</key>
<integer>14</integer>
<key>line</key>
<integer>231</integer>
</dict>
</dict>
<key>avr/bootloader/config.h</key>
<dict>
<key>caret</key>
<dict>
<key>column</key>
<integer>0</integer>
<key>line</key>
<integer>22</integer>
</dict>
<key>firstVisibleColumn</key>
<integer>0</integer>
<key>firstVisibleLine</key>
<integer>0</integer>
</dict>
<key>avr/usbload/fat.c</key>
<dict>
<key>caret</key>
<dict>
<key>column</key>
<integer>0</integer>
<key>line</key>
<integer>207</integer>
</dict>
<key>firstVisibleColumn</key>
<integer>0</integer>
<key>firstVisibleLine</key>
<integer>613</integer>
</dict>
<key>avr/usbload/fat.h</key>
<dict>
<key>caret</key>
<dict>
<key>column</key>
<integer>28</integer>
<key>line</key>
<integer>21</integer>
</dict>
<key>columnSelection</key>
<false/>
<key>firstVisibleColumn</key>
<integer>0</integer>
<key>firstVisibleLine</key>
<integer>0</integer>
<key>selectFrom</key>
<dict>
<key>column</key>
<integer>23</integer>
<key>line</key>
<integer>21</integer>
</dict>
<key>selectTo</key>
<dict>
<key>column</key>
<integer>34</integer>
<key>line</key>
<integer>21</integer>
</dict>
</dict>
<key>avr/usbload/file.c</key>
<dict>
<key>caret</key>
<dict>
<key>column</key>
<integer>45</integer>
<key>line</key>
<integer>135</integer>
</dict>
<key>columnSelection</key>
<false/>
<key>firstVisibleColumn</key>
<integer>0</integer>
<key>firstVisibleLine</key>
<integer>109</integer>
<key>selectFrom</key>
<dict>
<key>column</key>
<integer>41</integer>
<key>line</key>
<integer>135</integer>
</dict>
<key>selectTo</key>
<dict>
<key>column</key>
<integer>45</integer>
<key>line</key>
<integer>135</integer>
</dict>
</dict>
<key>avr/usbload/file.h</key>
<dict>
<key>caret</key>
<dict>
@ -33,6 +153,208 @@
<key>firstVisibleLine</key>
<integer>0</integer>
</dict>
<key>avr/usbload/main.c</key>
<dict>
<key>caret</key>
<dict>
<key>column</key>
<integer>0</integer>
<key>line</key>
<integer>25</integer>
</dict>
<key>columnSelection</key>
<false/>
<key>firstVisibleColumn</key>
<integer>0</integer>
<key>firstVisibleLine</key>
<integer>293</integer>
<key>selectFrom</key>
<dict>
<key>column</key>
<integer>0</integer>
<key>line</key>
<integer>24</integer>
</dict>
<key>selectTo</key>
<dict>
<key>column</key>
<integer>0</integer>
<key>line</key>
<integer>25</integer>
</dict>
</dict>
<key>avr/usbload/mmc.c</key>
<dict>
<key>caret</key>
<dict>
<key>column</key>
<integer>0</integer>
<key>line</key>
<integer>224</integer>
</dict>
<key>firstVisibleColumn</key>
<integer>0</integer>
<key>firstVisibleLine</key>
<integer>173</integer>
</dict>
<key>avr/usbload/mmc.h</key>
<dict>
<key>caret</key>
<dict>
<key>column</key>
<integer>0</integer>
<key>line</key>
<integer>39</integer>
</dict>
<key>firstVisibleColumn</key>
<integer>0</integer>
<key>firstVisibleLine</key>
<integer>0</integer>
</dict>
<key>avr/usbload/shared_memory.h</key>
<dict>
<key>caret</key>
<dict>
<key>column</key>
<integer>0</integer>
<key>line</key>
<integer>0</integer>
</dict>
<key>firstVisibleColumn</key>
<integer>0</integer>
<key>firstVisibleLine</key>
<integer>0</integer>
</dict>
<key>avr/usbload/testing.c</key>
<dict>
<key>caret</key>
<dict>
<key>column</key>
<integer>17</integer>
<key>line</key>
<integer>130</integer>
</dict>
<key>firstVisibleColumn</key>
<integer>0</integer>
<key>firstVisibleLine</key>
<integer>31</integer>
</dict>
<key>avr/usbload/testing.h</key>
<dict>
<key>caret</key>
<dict>
<key>column</key>
<integer>0</integer>
<key>line</key>
<integer>0</integer>
</dict>
<key>firstVisibleColumn</key>
<integer>0</integer>
<key>firstVisibleLine</key>
<integer>0</integer>
</dict>
<key>poc/avr_sdcard/fat.c</key>
<dict>
<key>caret</key>
<dict>
<key>column</key>
<integer>0</integer>
<key>line</key>
<integer>38</integer>
</dict>
<key>firstVisibleColumn</key>
<integer>0</integer>
<key>firstVisibleLine</key>
<integer>0</integer>
</dict>
<key>poc/avr_sdcard/fat.h</key>
<dict>
<key>caret</key>
<dict>
<key>column</key>
<integer>4</integer>
<key>line</key>
<integer>63</integer>
</dict>
<key>columnSelection</key>
<false/>
<key>firstVisibleColumn</key>
<integer>0</integer>
<key>firstVisibleLine</key>
<integer>23</integer>
<key>selectFrom</key>
<dict>
<key>column</key>
<integer>1</integer>
<key>line</key>
<integer>63</integer>
</dict>
<key>selectTo</key>
<dict>
<key>column</key>
<integer>9</integer>
<key>line</key>
<integer>63</integer>
</dict>
</dict>
<key>poc/avr_sdcard/main.c</key>
<dict>
<key>caret</key>
<dict>
<key>column</key>
<integer>12</integer>
<key>line</key>
<integer>170</integer>
</dict>
<key>columnSelection</key>
<false/>
<key>firstVisibleColumn</key>
<integer>0</integer>
<key>firstVisibleLine</key>
<integer>137</integer>
<key>selectFrom</key>
<dict>
<key>column</key>
<integer>1</integer>
<key>line</key>
<integer>170</integer>
</dict>
<key>selectTo</key>
<dict>
<key>column</key>
<integer>20</integer>
<key>line</key>
<integer>170</integer>
</dict>
</dict>
<key>poc/avr_sdcard/main.lst</key>
<dict>
<key>caret</key>
<dict>
<key>column</key>
<integer>0</integer>
<key>line</key>
<integer>0</integer>
</dict>
<key>firstVisibleColumn</key>
<integer>0</integer>
<key>firstVisibleLine</key>
<integer>0</integer>
</dict>
<key>poc/avr_usbload/sram.c</key>
<dict>
<key>caret</key>
<dict>
<key>column</key>
<integer>0</integer>
<key>line</key>
<integer>22</integer>
</dict>
<key>firstVisibleColumn</key>
<integer>0</integer>
<key>firstVisibleLine</key>
<integer>0</integer>
</dict>
<key>snes/banktest/LoadGraphics.asm</key>
<dict>
<key>caret</key>
@ -62,6 +384,26 @@
<integer>211</integer>
</dict>
</dict>
<key>openDocuments</key>
<array>
<string>avr/usbload/mmc.c</string>
<string>avr/usbload/testing.h</string>
<string>avr/usbload/testing.c</string>
<string>poc/avr_sdcard/fat.c</string>
<string>poc/avr_sdcard/fat.h</string>
<string>poc/avr_sdcard/main.lst</string>
<string>avr/bootloader/config.h</string>
<string>avr/bootloader/bootloader.c</string>
<string>poc/avr_sdcard/main.c</string>
<string>poc/avr_usbload/sram.c</string>
<string>avr/usbload/file.c</string>
<string>avr/usbload/file.h</string>
<string>avr/usbload/mmc.h</string>
<string>avr/usbload/shared_memory.h</string>
<string>avr/usbload/fat.c</string>
<string>avr/usbload/fat.h</string>
<string>avr/usbload/main.c</string>
</array>
<key>showFileHierarchyDrawer</key>
<false/>
<key>showFileHierarchyPanel</key>
@ -80,7 +422,7 @@
<true/>
<key>subItems</key>
<dict>
<key>usbload</key>
<key>bootloader</key>
<dict>
<key>isExpanded</key>
<true/>