1 #ifndef LIBPROPELLER_SD_H_ 
    2 #define LIBPROPELLER_SD_H_ 
    8 #define RET_IF_ERROR_NULL if(HasError()){return NULL;} 
    9 #define RET_IF_ERROR if(HasError()){return;} 
   10 #define THROW_NULL(value) {SetErrorCode((value)); return NULL;} 
   12 #define THROW(value) {SetErrorCode((value)); return;} 
  112         Mount(basepin, (basepin + 1), (basepin + 2), (basepin + 3));
 
  122     void Mount(
const int pin_do, 
const int pin_clk, 
const int pin_di, 
const int pin_cs) {
 
  123         if (file_date_time_ == 0) {
 
  131         if ((((
int) buffer_1_) & 0b11) != 0)
 
  133         if ((((
int) buffer_2_) & 0b11) != 0)
 
  139         sd_spi_.
Start(pin_do, pin_clk, pin_di, pin_cs);
 
  144         sd_spi_.
ReadBlock(0, (
char *) (&buffer_1_));
 
  148         if (GetFilesystemType() != kFileSystemUnknown) {
 
  151             start = ReverseBytesInLong(((
char *) (&buffer_1_) + 0x1C6));
 
  155         filesystem_ = GetFilesystemType();
 
  156         if (filesystem_ == kFileSystemUnknown) {
 
  159         if (ReverseBytesInWord(((
char *) (&buffer_1_) + 11)) != kSectorSize) {
 
  162         int sectors_per_cluster = buffer_1_[13];
 
  163         if (sectors_per_cluster & (sectors_per_cluster - 1)) {
 
  167         while (sectors_per_cluster > 1) {
 
  169             sectors_per_cluster = (Shr__(sectors_per_cluster, 1));
 
  171         sectors_per_cluster = (1 << cluster_shift_);
 
  172         cluster_size_ = (kSectorSize << cluster_shift_);
 
  173         int reserved = ReverseBytesInWord(((
char *) (&buffer_1_) + 14));
 
  174         if (buffer_1_[16] != 2) {
 
  177         int sectors = ReverseBytesInWord(((
char *) (&buffer_1_) + 19));
 
  179             sectors = ReverseBytesInLong(((
char *) (&buffer_1_) + 32));
 
  181         fat1_ = (start + reserved);
 
  182         if (filesystem_ == kFileSystemFAT32) {
 
  183             int root_entries = (16 << cluster_shift_);
 
  184             sectors_per_fat_ = ReverseBytesInLong(((
char *) (&buffer_1_) + 36));
 
  185             data_region_ = ((fat1_ + (2 * sectors_per_fat_)) - (2 * sectors_per_cluster));
 
  186             root_directory_ = ((data_region_ + (ReverseBytesInWord(((
char *) (&buffer_1_) + 44)) << cluster_shift_)) << kSectorShift);
 
  187             root_directory_end_ = (root_directory_ + (root_entries << kDirectoryShift));
 
  188             end_of_chain_ = 268435440;
 
  190             int root_entries = ReverseBytesInWord(((
char *) (&buffer_1_) + 17));
 
  191             sectors_per_fat_ = ReverseBytesInWord(((
char *) (&buffer_1_) + 22));
 
  192             root_directory_ = ((fat1_ + (2 * sectors_per_fat_)) << kSectorShift);
 
  193             root_directory_end_ = (root_directory_ + (root_entries << kDirectoryShift));
 
  194             data_region_ = ((1 + (Shr__((root_directory_end_ - 1), kSectorShift))) - (2 * sectors_per_cluster));
 
  195             end_of_chain_ = 65520;
 
  197         if (ReverseBytesInWord(((
char *) (&buffer_1_) + 510)) != 43605) {
 
  200         total_clusters_ = (Shr__(((sectors - data_region_) + start), cluster_shift_));
 
  229     void Open(
const char * filename, 
const char file_mode) {
 
  234         char cleaned_filename[11];
 
  237         while (I < 8 && filename[0] != 
'\0' && filename[0] != 
'.') {
 
  238             cleaned_filename[(I++)] = ConvertToUppercase((filename++)[0]);
 
  241             cleaned_filename[(I++)] = 
' ';
 
  243         while (filename[0] != 
'\0' && filename[0] != 
'.') {
 
  246         if ((filename)[0] == 
'.') {
 
  249         while ((I < 11) && ((filename)[0])) {
 
  250             cleaned_filename[(I++)] = ConvertToUppercase((filename++)[0]);
 
  253             cleaned_filename[(I++)] = 
' ';
 
  267         for (
int directory_pointer = root_directory_;
 
  268                 directory_pointer <= root_directory_end_ - kDirectorySize;
 
  269                 directory_pointer += kDirectorySize) {
 
  270             char * disk_filename = ReadByte(directory_pointer);
 
  273             if ((free_entry == 0) && (((disk_filename)[0] == 0) || ((disk_filename)[0] == 0xe5))) {
 
  274                 free_entry = directory_pointer;
 
  276             if ((disk_filename)[0] == 0) {
 
  277                 sentinel = directory_pointer;
 
  283             for (; i <= 10; i++) {
 
  284                 if (cleaned_filename[i] != (disk_filename)[i]) {
 
  290             if ((i == 11) && (0 == ((disk_filename)[0x0b] & 0x18))) { 
 
  291                 current_cluster_ = ReverseBytesInWord((disk_filename + 0x1a));
 
  292                 if (filesystem_ == kFileSystemFAT32) {
 
  293                     current_cluster_ = (current_cluster_ + (ReverseBytesInWord((disk_filename + 0x14)) << 16));
 
  295                 first_cluster_of_file_ = current_cluster_;
 
  296                 total_filesize_ = ReverseBytesInLong((disk_filename + 0x1c));
 
  299                 if (file_mode == 
'r') {
 
  303                 if ((disk_filename)[11] & 0xd9) {
 
  308                 if (file_mode == 
'd') {
 
  309                     OpenForDelete(disk_filename);
 
  311                 } 
else if (file_mode == 
'w') {
 
  312                     OpenForWrite(disk_filename, directory_pointer);
 
  314                 } 
else if (file_mode == 
'a') {
 
  315                     OpenForAppend(directory_pointer);
 
  324         if (file_mode == 
'd') { 
 
  328         if ((file_mode != 
'w') && (file_mode != 
'a')) {
 
  331         directory_entry_position_ = free_entry;
 
  332         if (directory_entry_position_ == 0) {
 
  337         char * S = ReadByte(directory_entry_position_);
 
  339         memset((
void *) S, 0, kDirectorySize);
 
  340         memcpy((
void *) S, (
void *) &cleaned_filename, 11);
 
  341         WriteReversedWord((S + 0x1a), 0);
 
  342         WriteReversedWord((S + 0x14), 0);
 
  343         WriteReversedLong((S + 0x0e), file_date_time_); 
 
  344         WriteReversedLong((S + 0x16), file_date_time_); 
 
  345         if ((directory_entry_position_ == sentinel) && ((directory_entry_position_ + kDirectorySize) < root_directory_end_)) {
 
  346             WriteReversedWord(ReadByte((directory_entry_position_ + kDirectorySize)), 0);
 
  351         cluster_write_offset_ = 0;
 
  352         current_cluster_ = 0;
 
  353         buffer_end_ = kSectorSize;
 
  365         if (directory_entry_position_) {
 
  369         current_buffer_location_ = 0;
 
  373         remaining_cluster_bytes_ = 0;
 
  374         cluster_write_offset_ = 0;
 
  375         directory_entry_position_ = 0;
 
  376         current_cluster_ = 0;
 
  377         first_cluster_of_file_ = 0;
 
  388         if (current_buffer_location_ >= buffer_end_) {
 
  395         return buffer_1_[(current_buffer_location_++)];
 
  408     int Get(
char * read_buffer, 
int bytes_to_read_count) {
 
  411         while (bytes_to_read_count > 0) {
 
  412             if (current_buffer_location_ >= buffer_end_) {
 
  421             T = (Min__((buffer_end_ - current_buffer_location_), bytes_to_read_count));
 
  422             if (((T | (
int) read_buffer) | current_buffer_location_) & 0x3) {
 
  423                 memcpy((
void *) read_buffer, (
void *) (
void *) (((
int) (&buffer_1_) + current_buffer_location_)), 1 * (T));
 
  425                 memmove((
void *) read_buffer, (
void *) (
void *) (((
int) (&buffer_1_) + current_buffer_location_)), 4 * ((Shr__(T, 2))));
 
  427             current_buffer_location_ = (current_buffer_location_ + T);
 
  429             read_buffer = (read_buffer + T);
 
  430             bytes_to_read_count = (bytes_to_read_count - T);
 
  441         if (current_buffer_location_ == kSectorSize) {
 
  442             if (FlushBuffer(kSectorSize, 0) < 0) {
 
  446         buffer_1_[(current_buffer_location_++)] = C;
 
  458         return Put(B, strlen(B));
 
  469     int Put(
const char * buffer, 
int byte_count) {
 
  470         int total_bytes_written = 0;
 
  471         while (byte_count > 0) {
 
  472             if (current_buffer_location_ >= buffer_end_) {
 
  473                 FlushBuffer(current_buffer_location_, 0);
 
  477             int bytes_to_write = (Min__((buffer_end_ - current_buffer_location_), byte_count));
 
  478             memcpy((
void *) (
void *) (((
int) (&buffer_1_) + current_buffer_location_)), (
void *) buffer, bytes_to_write);
 
  480             total_bytes_written = (total_bytes_written + bytes_to_write);
 
  481             current_buffer_location_ = (current_buffer_location_ + bytes_to_write);
 
  482             buffer = (buffer + bytes_to_write);
 
  483             byte_count = (byte_count - bytes_to_write);
 
  485         return total_bytes_written;
 
  497         int off = (root_directory_ - (data_region_ << kSectorShift));
 
  498         current_cluster_ = (Shr__(off, (cluster_shift_ + kSectorShift)));
 
  499         seek_position_ = (off - (current_cluster_ << (cluster_shift_ + kSectorShift)));
 
  500         remaining_cluster_bytes_ = (root_directory_end_ - root_directory_);
 
  501         total_filesize_ = (seek_position_ + remaining_cluster_bytes_);
 
  513             if (current_buffer_location_ >= buffer_end_) {
 
  514                 if (FillBuffer() < 0) {
 
  517                 if (((Shr__(seek_position_, kSectorShift)) & ((1 << cluster_shift_) - 1)) == 0) {
 
  518                     (current_cluster_++);
 
  522             unsigned char * at = (
unsigned char *) ((
int) &buffer_1_ + current_buffer_location_);
 
  527             current_buffer_location_ = (current_buffer_location_ + kDirectorySize);
 
  528             if (((at)[0] != 0xe5)
 
  529                     && (((at)[0x0b] & 0x18) == 0)) {
 
  530                 char * lns = filename;
 
  532                 for (
int i = 0; i <= 10; i++) {
 
  533                     filename[0] = (at)[i];
 
  538                     if (i == 7 || i == 10) {
 
  562         if (((directory_entry_position_) || (position < 0)) || (position > total_filesize_)) {
 
  565         int delta = ((seek_position_ - buffer_end_) & (-cluster_size_));
 
  566         if (position < delta) {
 
  567             current_cluster_ = first_cluster_of_file_;
 
  568             remaining_cluster_bytes_ = (Min__(cluster_size_, total_filesize_));
 
  570             current_buffer_location_ = 0;
 
  574         while (position >= (delta + cluster_size_)) {
 
  575             current_cluster_ = NextCluster();
 
  578             seek_position_ = (seek_position_ + cluster_size_);
 
  579             delta = (delta + cluster_size_);
 
  580             remaining_cluster_bytes_ = (Min__(cluster_size_, (total_filesize_ - seek_position_)));
 
  581             current_buffer_location_ = 0;
 
  585                 || position < (seek_position_ - buffer_end_)
 
  586                 || position >= (seek_position_ - buffer_end_) + kSectorSize
 
  589             int delta_2 = (seek_position_ + remaining_cluster_bytes_);
 
  590             seek_position_ = (position & -kSectorSize);
 
  591             remaining_cluster_bytes_ = (delta_2 - seek_position_);
 
  595         current_buffer_location_ = position & (kSectorSize - 1);
 
  616     int SetDate(
const int year, 
const int month, 
const int day,
 
  617             const int hour, 
const int minute, 
const int second) {
 
  618         file_date_time_ = ((year - 1980) << 25) + (month << 21) + (day << 16);
 
  619         file_date_time_ += (hour << 11) + (minute << 5) + (second >> 1);
 
  620         return file_date_time_;
 
  655         return cluster_size_;
 
  665         return total_clusters_;
 
  673         return total_filesize_;
 
  679     static const int kFileSystemUnknown = 0;
 
  680     static const int kFileSystemFAT16 = 1;
 
  681     static const int kFileSystemFAT32 = 2;
 
  684     static const int kSectorSize = 512;
 
  685     static const int kSectorShift = 9;
 
  686     static const int kDirectorySize = 32;
 
  687     static const int kDirectoryShift = 5;
 
  691     int current_cluster_;
 
  694     int remaining_cluster_bytes_;
 
  695     int current_buffer_location_;
 
  697     int directory_entry_position_;
 
  698     int cluster_write_offset_;
 
  700     int first_cluster_of_file_;
 
  704     int root_directory_end_;
 
  710     int sectors_per_fat_;
 
  735     void SetErrorCode(
const int abort_code) {
 
  742     void WriteBlock(
const int block_index, 
char * buffer_address) {
 
  743         sd_spi_.
WriteBlock(block_index, buffer_address);
 
  745         if (block_index >= fat1_) {
 
  746             if (block_index < (fat1_ + sectors_per_fat_)) {
 
  747                 sd_spi_.
WriteBlock(block_index + sectors_per_fat_, buffer_address);
 
  755     void FlushIfDirty(
void) {
 
  757             WriteBlock(last_read_, buffer_2_);
 
  765     void ReadBlock(
const int block_index) {
 
  766         if (block_index != last_read_) {
 
  769             sd_spi_.
ReadBlock(block_index, buffer_2_);
 
  771             last_read_ = block_index;
 
  777     int ReverseBytesInWord(
const char * data)
 const {
 
  778         return ((data)[0] + ((data)[1] << 8));
 
  783     int ReverseBytesInLong(
const char * data)
 const {
 
  784         return (ReverseBytesInWord(data) + (ReverseBytesInWord((data + 2)) << 16));
 
  789     int ReverseBytesInCluster(
const char * cluster)
 const {
 
  790         if (filesystem_ == kFileSystemFAT16) {
 
  791             return ReverseBytesInWord(cluster);
 
  793             return ReverseBytesInLong(cluster);
 
  799     void WriteReversedWord(
char * result, 
const int data) {
 
  801         result[0] = data >> 8;
 
  807     void WriteReversedLong(
char * result, 
const int data) {
 
  808         WriteReversedWord(result, data);
 
  809         WriteReversedWord(result + 2, data >> 16);
 
  814     void WriteReversedCluster(
char * result, 
const int data) {
 
  816         if (filesystem_ == kFileSystemFAT16) {
 
  817             WriteReversedWord(result, data);
 
  819             WriteReversedLong(result, data);
 
  823     int GetFilesystemType(
void) {
 
  824         const int kFAT1 = 
'F' + (
'A' << 8) + (
'T' << 16) + (
'1' << 24);
 
  825         const int kFAT3 = 
'F' + (
'A' << 8) + (
'T' << 16) + (
'3' << 24);
 
  827         if ((ReverseBytesInLong(&buffer_1_[0x36]) == kFAT1) && (buffer_1_[58] == 
'6')) {
 
  828             return kFileSystemFAT16;
 
  830         if ((ReverseBytesInLong(&buffer_1_[0x52]) == kFAT3) && (buffer_1_[86] == 
'2')) {
 
  831             return kFileSystemFAT32;
 
  833         return kFileSystemUnknown;
 
  838     char * ReadByte(
const int Byteloc) {
 
  839         ReadBlock((Shr__(Byteloc, kSectorShift)));
 
  842         return ((
char *) (&buffer_2_) + (Byteloc & 0x1ff));
 
  847     char * ReadFAT(
const int Clust) {
 
  848         last_fat_entry_ = ((fat1_ << kSectorShift) + (Clust << filesystem_));
 
  849         return ReadByte(last_fat_entry_);
 
  854     int FollowFATChain(
void) {
 
  855         char * temp = ReadFAT(current_cluster_);
 
  857         cluster_write_offset_ = last_fat_entry_;
 
  858         return ReverseBytesInCluster(temp);
 
  863     int NextCluster(
void) {
 
  864         int result = FollowFATChain();
 
  866         if ((result < 2) || (result >= total_clusters_)) {
 
  874     void FreeClusters(
int cluster) {
 
  875         while (cluster < end_of_chain_) {
 
  879             char * byte_pointer = ReadFAT(cluster);
 
  882             cluster = ReverseBytesInCluster(byte_pointer);
 
  883             WriteReversedCluster(byte_pointer, 0);
 
  899     int CalculateCurrentBlockAddress(
void)
 const {
 
  900         return (current_cluster_ << cluster_shift_) +data_region_
 
  901                 + (Shr__(seek_position_, kSectorShift) & ((1 << cluster_shift_) - 1));
 
  907     char ConvertToUppercase(
const char character)
 const {
 
  908         if ((
'a' <= character) && (character <= 
'z')) {
 
  909             return (character - 32);
 
  916     int FlushBuffer(
int r_cnt, 
const int flush_metadata) {
 
  917         if (directory_entry_position_ == 0) {
 
  921             if (remaining_cluster_bytes_ < kSectorSize) {
 
  924                 int Newcluster = (-1);
 
  925                 int Cluststart = (current_cluster_ & (~((Shr__(kSectorSize, filesystem_)) - 1)));
 
  933                         int _limit__0025 = (kSectorSize - (1 << filesystem_));
 
  934                         int _step__0026 = (1 << filesystem_);
 
  936                         if (I >= _limit__0025) _step__0026 = -_step__0026;
 
  938                             if (buffer_2_[I] == 0) {
 
  939                                 if (ReverseBytesInCluster(((
char *) (&buffer_2_) + I)) == 0) {
 
  940                                     Newcluster = (Cluststart + (Shr__(I, filesystem_)));
 
  941                                     if (Newcluster >= total_clusters_) {
 
  947                             I = (I + _step__0026);
 
  948                         } 
while (((_step__0026 > 0) && (I <= _limit__0025)) || ((_step__0026 < 0) && (I >= _limit__0025)));
 
  950                     if (Newcluster > 1) {
 
  951                         WriteReversedCluster(((
char *) (&buffer_2_) + I), (end_of_chain_ + 15));
 
  952                         if (cluster_write_offset_ == 0) {
 
  953                             WriteReversedWord((ReadByte(directory_entry_position_) + 26), Newcluster);
 
  954                             cluster_write_offset_ = (directory_entry_position_ & (kSectorSize - filesystem_));
 
  955                             WriteReversedLong((((
char *) (&buffer_2_) + cluster_write_offset_) + 28), (seek_position_ + current_buffer_location_));
 
  956                             if (filesystem_ == kFileSystemFAT32) {
 
  957                                 WriteReversedWord((((
char *) (&buffer_2_) + cluster_write_offset_) + 20), (Shr__(Newcluster, 16)));
 
  960                             WriteReversedCluster(ReadByte(cluster_write_offset_), Newcluster);
 
  962                         cluster_write_offset_ = (last_fat_entry_ + I);
 
  963                         current_cluster_ = Newcluster;
 
  964                         remaining_cluster_bytes_ = cluster_size_;
 
  967                         Cluststart = (Cluststart + (Shr__(kSectorSize, filesystem_)));
 
  968                         if (Cluststart >= total_clusters_) {
 
  979             if (remaining_cluster_bytes_ >= kSectorSize) {
 
  980                 sd_spi_.
WriteBlock(CalculateCurrentBlockAddress(), (
char *) (&buffer_1_));
 
  983                 if (r_cnt == kSectorSize) { 
 
  984                     seek_position_ = (seek_position_ + r_cnt);
 
  985                     remaining_cluster_bytes_ = (remaining_cluster_bytes_ - r_cnt);
 
  986                     current_buffer_location_ = 0;
 
  991         if ((r_cnt < 0) || (flush_metadata)) { 
 
  992             ReadBlock((Shr__(directory_entry_position_, kSectorShift))); 
 
  995             WriteReversedLong((((
char *) (&buffer_2_) + (directory_entry_position_ & (kSectorSize - filesystem_))) + 28), (seek_position_ + current_buffer_location_));
 
 1008         return FlushBuffer(current_buffer_location_, 1);
 
 1013     int FillBuffer(
void) {
 
 1014         if (seek_position_ >= total_filesize_) {
 
 1017         if (remaining_cluster_bytes_ == 0) {
 
 1018             current_cluster_ = NextCluster();
 
 1019             if (current_cluster_ < 0) {
 
 1020                 return current_cluster_;
 
 1022             remaining_cluster_bytes_ = (Min__(cluster_size_, (total_filesize_ - seek_position_)));
 
 1024         sd_spi_.
ReadBlock(CalculateCurrentBlockAddress(), buffer_1_);
 
 1027         int bytes_read = kSectorSize;
 
 1028         if ((seek_position_ + bytes_read) >= total_filesize_) {
 
 1029             bytes_read = (total_filesize_ - seek_position_);
 
 1031         seek_position_ = (seek_position_ + bytes_read);
 
 1032         remaining_cluster_bytes_ = (remaining_cluster_bytes_ - bytes_read);
 
 1033         current_buffer_location_ = 0;
 
 1034         buffer_end_ = bytes_read;
 
 1041     void OpenForRead(
void) {
 
 1042         remaining_cluster_bytes_ = (Min__(cluster_size_, total_filesize_));
 
 1049     void OpenForDelete(
char * 
string) {
 
 1050         WriteReversedWord(
string, 0xe5);
 
 1051         if (current_cluster_) {
 
 1052             FreeClusters(current_cluster_);
 
 1061     void OpenForWrite(
char * 
string, 
const int dir_pointer) {
 
 1062         WriteReversedWord((
string + 0x1a), 0);
 
 1063         WriteReversedWord((
string + 0x14), 0);
 
 1064         WriteReversedLong((
string + 0x1c), 0);
 
 1065         cluster_write_offset_ = 0;
 
 1066         directory_entry_position_ = dir_pointer;
 
 1067         if (current_cluster_) {
 
 1068             FreeClusters(current_cluster_);
 
 1072         buffer_end_ = kSectorSize;
 
 1073         current_cluster_ = 0;
 
 1074         total_filesize_ = 0;
 
 1075         remaining_cluster_bytes_ = 0;
 
 1084     void OpenForAppend(
const int dir_pointer) {
 
 1086         remaining_cluster_bytes_ = total_filesize_;
 
 1087         int free_entry = cluster_size_;
 
 1088         if (current_cluster_ >= end_of_chain_) {
 
 1089             current_cluster_ = 0;
 
 1091         while (remaining_cluster_bytes_ > free_entry) {
 
 1092             if (current_cluster_ < 2) {
 
 1095             current_cluster_ = NextCluster();
 
 1098             remaining_cluster_bytes_ = (remaining_cluster_bytes_ - free_entry);
 
 1100         seek_position_ = (total_filesize_ & !(kSectorSize - 1));
 
 1101         buffer_end_ = kSectorSize;
 
 1102         current_buffer_location_ = (remaining_cluster_bytes_ & 0x1ff);
 
 1103         cluster_write_offset_ = 0;
 
 1104         directory_entry_position_ = dir_pointer;
 
 1105         if (current_buffer_location_) {
 
 1106             sd_spi_.
ReadBlock(CalculateCurrentBlockAddress(), (
char *) (&buffer_1_));
 
 1109             remaining_cluster_bytes_ = (free_entry - (seek_position_ & (free_entry - 1)));
 
 1111             if ((current_cluster_ < 2) || (remaining_cluster_bytes_ == free_entry)) {
 
 1112                 remaining_cluster_bytes_ = 0;
 
 1114                 remaining_cluster_bytes_ = (free_entry - (seek_position_ & (free_entry - 1)));
 
 1117         if (current_cluster_ >= 2) {
 
 1130     static int Min__(
const int a, 
const int b) {
 
 1131         return a < b ? a : 
b;
 
 1140     static int Shr__(
const unsigned int a, 
const unsigned int b) {
 
 1146 #endif // LIBPROPELLER_SD_H_