mFS file system library for EEPROM memory chips.

Committer:
HBP
Date:
Tue Feb 22 18:57:37 2011 +0000
Revision:
9:52c01cb100ac
Parent:
7:5ac5121bb4e0
Child:
10:211cb54339a0
-file rename
-Increased fault tolerance

Who changed what in which revision?

UserRevisionLine numberNew contents of line
HBP 5:a0fe74dce80d 1 /*CPP**************************************************************************
HBP 7:5ac5121bb4e0 2 * FILENAME : mfs.cpp *
HBP 7:5ac5121bb4e0 3 * *
HBP 7:5ac5121bb4e0 4 * DESCRIPTION : *
HBP 7:5ac5121bb4e0 5 * mFS file system implementation for mBED with external I2C EEEPROM. *
HBP 7:5ac5121bb4e0 6 * *
HBP 7:5ac5121bb4e0 7 * AUTHOR : Olli Vanhoja START DATE : 2011-02-21 *
HBP 7:5ac5121bb4e0 8 *****************************************************************************/
HBP 0:cbf45dde2b49 9
HBP 0:cbf45dde2b49 10 #include "mbed.h"
HBP 0:cbf45dde2b49 11 #include "mfs.h"
HBP 0:cbf45dde2b49 12 #include "i2c_eeprom.h"
HBP 0:cbf45dde2b49 13
HBP 0:cbf45dde2b49 14 #define RB 3 // Reseved bytes per block (1 attrb B, 2 B for next/prev pointers
HBP 0:cbf45dde2b49 15 #define DEBUG // Adds extra safety to reading and writing
HBP 0:cbf45dde2b49 16
HBP 0:cbf45dde2b49 17 DigitalOut FlushLed(LED2);
HBP 0:cbf45dde2b49 18
HBP 0:cbf45dde2b49 19 mfs::mfs(int i2c_address)
HBP 0:cbf45dde2b49 20 {
HBP 5:a0fe74dce80d 21 mem = new i2c_eeprom(i2c_address, 200000);
HBP 0:cbf45dde2b49 22 }
HBP 0:cbf45dde2b49 23
HBP 9:52c01cb100ac 24 char mfs::read(char *data, char block, uint32_t byte, uint32_t n)
HBP 0:cbf45dde2b49 25 {
HBP 0:cbf45dde2b49 26 // Faster reading without DEBUG mode
HBP 0:cbf45dde2b49 27 #ifdef DEBUG
HBP 0:cbf45dde2b49 28 if ((byte+n-1 >= BS))
HBP 0:cbf45dde2b49 29 return 1;
HBP 0:cbf45dde2b49 30 #endif
HBP 0:cbf45dde2b49 31 mem->read(BS*block+byte, n, data);
HBP 5:a0fe74dce80d 32 //wait_ms(1);
HBP 0:cbf45dde2b49 33 return 0;
HBP 0:cbf45dde2b49 34 }
HBP 0:cbf45dde2b49 35
HBP 9:52c01cb100ac 36 char mfs::write(char *data, char block, uint32_t byte, uint32_t n)
HBP 0:cbf45dde2b49 37 {
HBP 0:cbf45dde2b49 38 // Faster writing without DEBUG mode
HBP 0:cbf45dde2b49 39 #ifdef DEBUG
HBP 0:cbf45dde2b49 40 if (byte+n >= BS)
HBP 0:cbf45dde2b49 41 return 1;
HBP 0:cbf45dde2b49 42 #endif
HBP 0:cbf45dde2b49 43 mem->write(data, BS*block+byte, n);
HBP 0:cbf45dde2b49 44 return 0;
HBP 0:cbf45dde2b49 45 }
HBP 0:cbf45dde2b49 46
HBP 0:cbf45dde2b49 47 char mfs::getNextFreeBlock(char *blockOut)
HBP 0:cbf45dde2b49 48 {
HBP 0:cbf45dde2b49 49 // Locate free block by seeking EERPOM
HBP 0:cbf45dde2b49 50 char cFlags[1];
HBP 0:cbf45dde2b49 51
HBP 0:cbf45dde2b49 52 for (*blockOut=0; *blockOut < BC; (*blockOut)++)
HBP 0:cbf45dde2b49 53 {
HBP 0:cbf45dde2b49 54 read(cFlags, *blockOut, 0, 1);
HBP 0:cbf45dde2b49 55 if (cFlags[0] == 0x04)
HBP 0:cbf45dde2b49 56 break;
HBP 0:cbf45dde2b49 57 if (*blockOut >= BC-1)
HBP 0:cbf45dde2b49 58 return 1;
HBP 0:cbf45dde2b49 59 }
HBP 0:cbf45dde2b49 60
HBP 0:cbf45dde2b49 61 return 0;
HBP 0:cbf45dde2b49 62 }
HBP 0:cbf45dde2b49 63
HBP 9:52c01cb100ac 64 uint32_t mfs::findNextFile(char block, char *filenameOut)
HBP 0:cbf45dde2b49 65 {
HBP 9:52c01cb100ac 66 uint32_t i=block;
HBP 0:cbf45dde2b49 67 char cFlags[1];
HBP 0:cbf45dde2b49 68
HBP 0:cbf45dde2b49 69 while (i < BC)
HBP 0:cbf45dde2b49 70 {
HBP 0:cbf45dde2b49 71 read(cFlags, i, 0, 1);
HBP 0:cbf45dde2b49 72
HBP 0:cbf45dde2b49 73 if ((cFlags[0] & 0x8C) == 0x8C)
HBP 0:cbf45dde2b49 74 break; // File found
HBP 0:cbf45dde2b49 75 else
HBP 0:cbf45dde2b49 76 i++;
HBP 0:cbf45dde2b49 77 }
HBP 0:cbf45dde2b49 78
HBP 0:cbf45dde2b49 79 if(i == BC)
HBP 0:cbf45dde2b49 80 {
HBP 0:cbf45dde2b49 81 strcpy(filenameOut, "");
HBP 0:cbf45dde2b49 82 return 0xffff; // Empty fs
HBP 0:cbf45dde2b49 83 }
HBP 0:cbf45dde2b49 84
HBP 0:cbf45dde2b49 85 // Read filename
HBP 0:cbf45dde2b49 86 read(filenameOut, i, 3, 20);
HBP 0:cbf45dde2b49 87 return i; // Return block number
HBP 0:cbf45dde2b49 88 }
HBP 0:cbf45dde2b49 89
HBP 9:52c01cb100ac 90 uint32_t mfs::getFirstBlockOfFile(char filename[20])
HBP 0:cbf45dde2b49 91 {
HBP 9:52c01cb100ac 92 uint32_t block=0;
HBP 0:cbf45dde2b49 93 char tmpFilename[20]="";
HBP 0:cbf45dde2b49 94
HBP 0:cbf45dde2b49 95 while (block < BC)
HBP 0:cbf45dde2b49 96 {
HBP 0:cbf45dde2b49 97 block = findNextFile(block, tmpFilename);
HBP 0:cbf45dde2b49 98 if (block < BC)
HBP 0:cbf45dde2b49 99 {
HBP 0:cbf45dde2b49 100 if(strcmp(tmpFilename, filename) == 0)
HBP 0:cbf45dde2b49 101 return block; // File exists
HBP 0:cbf45dde2b49 102 }
HBP 0:cbf45dde2b49 103 else return 0xFFFF; // File doesn't exist
HBP 0:cbf45dde2b49 104 block++;
HBP 0:cbf45dde2b49 105 }
HBP 0:cbf45dde2b49 106
HBP 0:cbf45dde2b49 107 return 0xFFFF; // ??
HBP 0:cbf45dde2b49 108 }
HBP 0:cbf45dde2b49 109
HBP 0:cbf45dde2b49 110 char mfs::createFile(char filename[20])
HBP 0:cbf45dde2b49 111 {
HBP 0:cbf45dde2b49 112 char tmpFilename[20];
HBP 9:52c01cb100ac 113 uint32_t n;
HBP 0:cbf45dde2b49 114 char fb;
HBP 0:cbf45dde2b49 115
HBP 0:cbf45dde2b49 116 for (n=0; n < BC; n++)
HBP 0:cbf45dde2b49 117 {
HBP 0:cbf45dde2b49 118 n=findNextFile(n, tmpFilename);
HBP 0:cbf45dde2b49 119 if(n < BC)
HBP 0:cbf45dde2b49 120 {
HBP 0:cbf45dde2b49 121 if(strcmp(tmpFilename, filename) == 0)
HBP 0:cbf45dde2b49 122 return 1; // File exist
HBP 0:cbf45dde2b49 123 }
HBP 0:cbf45dde2b49 124 else break; // We already reached the edge of the universe
HBP 0:cbf45dde2b49 125 n++;
HBP 0:cbf45dde2b49 126 }
HBP 0:cbf45dde2b49 127
HBP 0:cbf45dde2b49 128 if(getNextFreeBlock(&fb))
HBP 0:cbf45dde2b49 129 return 2; // Out of space
HBP 0:cbf45dde2b49 130
HBP 0:cbf45dde2b49 131 char cData[23];
HBP 0:cbf45dde2b49 132 cData[0] = '\xCC'; // Necessary flags for file
HBP 0:cbf45dde2b49 133 cData[1] = '\0'; // Only this block yet
HBP 0:cbf45dde2b49 134 cData[2] = '\0'; // First block there could't be prev blocks
HBP 0:cbf45dde2b49 135
HBP 0:cbf45dde2b49 136 for (char i=0; i < 20; i++)
HBP 0:cbf45dde2b49 137 cData[3+i] = filename[i];
HBP 0:cbf45dde2b49 138
HBP 0:cbf45dde2b49 139 // Create file
HBP 0:cbf45dde2b49 140 write(cData, fb, 0, 23);
HBP 0:cbf45dde2b49 141
HBP 0:cbf45dde2b49 142 return 0;
HBP 0:cbf45dde2b49 143 }
HBP 0:cbf45dde2b49 144
HBP 0:cbf45dde2b49 145 char mfs::removeFile(char filename[20])
HBP 0:cbf45dde2b49 146 {
HBP 9:52c01cb100ac 147 uint32_t block;
HBP 0:cbf45dde2b49 148 char cData[3] = {'\0','\0','\0'};
HBP 0:cbf45dde2b49 149
HBP 0:cbf45dde2b49 150 // Check if file exists
HBP 0:cbf45dde2b49 151 block = getFirstBlockOfFile(filename);
HBP 0:cbf45dde2b49 152 if (block > BC)
HBP 0:cbf45dde2b49 153 return 1; // File not found
HBP 0:cbf45dde2b49 154
HBP 0:cbf45dde2b49 155 // Clear blocks reserver by the file
HBP 9:52c01cb100ac 156 uint32_t i=0;
HBP 0:cbf45dde2b49 157 char tmp_cData[2];
HBP 0:cbf45dde2b49 158 while(1)
HBP 0:cbf45dde2b49 159 {
HBP 0:cbf45dde2b49 160 read(cData, block, 0, 2);
HBP 0:cbf45dde2b49 161 tmp_cData[0] = cData[0];
HBP 0:cbf45dde2b49 162 tmp_cData[1] = cData[1];
HBP 0:cbf45dde2b49 163
HBP 0:cbf45dde2b49 164 // Clear the block
HBP 0:cbf45dde2b49 165 cData[0] = '\x04';
HBP 0:cbf45dde2b49 166 write(cData, block, 0, 3);
HBP 0:cbf45dde2b49 167
HBP 0:cbf45dde2b49 168 if ((tmp_cData[0] & 0x4C) != 0)
HBP 0:cbf45dde2b49 169 break; // End of File found
HBP 0:cbf45dde2b49 170 else if (i >= BC)
HBP 0:cbf45dde2b49 171 return 2; // fs is corrupted
HBP 0:cbf45dde2b49 172 block = tmp_cData[1];
HBP 0:cbf45dde2b49 173
HBP 0:cbf45dde2b49 174 i++;
HBP 0:cbf45dde2b49 175 }
HBP 0:cbf45dde2b49 176
HBP 0:cbf45dde2b49 177 return 0; // Everything went better than expected
HBP 0:cbf45dde2b49 178 }
HBP 0:cbf45dde2b49 179
HBP 7:5ac5121bb4e0 180 char mfs::renameFile(char oldFilename[20], char newFilename[20])
HBP 7:5ac5121bb4e0 181 {
HBP 9:52c01cb100ac 182 uint32_t block;
HBP 7:5ac5121bb4e0 183
HBP 7:5ac5121bb4e0 184 // Check if file exists
HBP 7:5ac5121bb4e0 185 block = getFirstBlockOfFile(oldFilename);
HBP 7:5ac5121bb4e0 186 if (block > BC)
HBP 7:5ac5121bb4e0 187 return 1; // File not found
HBP 7:5ac5121bb4e0 188
HBP 7:5ac5121bb4e0 189 write(newFilename, block, 3, 20);
HBP 7:5ac5121bb4e0 190
HBP 7:5ac5121bb4e0 191 return 0; // Everything went better than expected
HBP 7:5ac5121bb4e0 192 }
HBP 7:5ac5121bb4e0 193
HBP 0:cbf45dde2b49 194 char mfs::setFileFlags(char *flags, char filename[20])
HBP 0:cbf45dde2b49 195 {
HBP 0:cbf45dde2b49 196 /* RO|HIDDEN|LOCK *
HBP 0:cbf45dde2b49 197 * H L */
HBP 0:cbf45dde2b49 198
HBP 9:52c01cb100ac 199 uint32_t n;
HBP 0:cbf45dde2b49 200 char cData[1] = {'\0'};
HBP 0:cbf45dde2b49 201
HBP 0:cbf45dde2b49 202 // Check if file exists
HBP 0:cbf45dde2b49 203 n = getFirstBlockOfFile(filename);
HBP 0:cbf45dde2b49 204 if (n > BC)
HBP 0:cbf45dde2b49 205 return 1; // File not found
HBP 0:cbf45dde2b49 206
HBP 0:cbf45dde2b49 207 read(cData, n, 0, 1);
HBP 0:cbf45dde2b49 208 cData[0] |= (flags[0] & 0x01)|((flags[0] & 0x02) << 3)|((flags[0] & 0x04) << 3);
HBP 0:cbf45dde2b49 209 write(cData, n, 0, 1);
HBP 0:cbf45dde2b49 210
HBP 0:cbf45dde2b49 211 return 0;
HBP 0:cbf45dde2b49 212 }
HBP 0:cbf45dde2b49 213
HBP 0:cbf45dde2b49 214 char mfs::getFileFlags(char *flags, char filename[20])
HBP 0:cbf45dde2b49 215 {
HBP 0:cbf45dde2b49 216 /* RO|HIDDEN|LOCK *
HBP 0:cbf45dde2b49 217 * H L */
HBP 0:cbf45dde2b49 218
HBP 9:52c01cb100ac 219 uint32_t n;
HBP 0:cbf45dde2b49 220 char cData[1] = {'\0'};
HBP 0:cbf45dde2b49 221
HBP 0:cbf45dde2b49 222 // Check if file exists
HBP 0:cbf45dde2b49 223 n = getFirstBlockOfFile(filename);
HBP 0:cbf45dde2b49 224 if (n > BC)
HBP 0:cbf45dde2b49 225 return 1; // File not found
HBP 0:cbf45dde2b49 226
HBP 0:cbf45dde2b49 227 read(cData, n, 0, 1);
HBP 0:cbf45dde2b49 228 flags[0] = (cData[0] & 0x01)|((cData[0] & 0x10) >> 3)|((cData[0] & 0x20) >> 3);
HBP 0:cbf45dde2b49 229
HBP 0:cbf45dde2b49 230 return 0;
HBP 0:cbf45dde2b49 231 }
HBP 0:cbf45dde2b49 232
HBP 0:cbf45dde2b49 233 // Return number of free blocks
HBP 9:52c01cb100ac 234 char mfs::free()
HBP 0:cbf45dde2b49 235 {
HBP 9:52c01cb100ac 236 char blocks=0;
HBP 9:52c01cb100ac 237 char r;
HBP 0:cbf45dde2b49 238 char cFlags[1];
HBP 0:cbf45dde2b49 239
HBP 0:cbf45dde2b49 240 for (r=0; r < BC; r++)
HBP 0:cbf45dde2b49 241 {
HBP 0:cbf45dde2b49 242 read(cFlags, r, 0, 1);
HBP 0:cbf45dde2b49 243 if (cFlags[0] == 0x04)
HBP 0:cbf45dde2b49 244 blocks++;
HBP 0:cbf45dde2b49 245 if (r >= BC-1)
HBP 0:cbf45dde2b49 246 return blocks;
HBP 0:cbf45dde2b49 247 }
HBP 0:cbf45dde2b49 248
HBP 0:cbf45dde2b49 249 return 0;
HBP 0:cbf45dde2b49 250 }
HBP 0:cbf45dde2b49 251
HBP 0:cbf45dde2b49 252 char mfs::mkfs(char createLabel)
HBP 0:cbf45dde2b49 253 {
HBP 0:cbf45dde2b49 254 unsigned int iAddr = 0;
HBP 9:52c01cb100ac 255 char i = 0;
HBP 9:52c01cb100ac 256 char bad = 0; // For counting bad block headers
HBP 0:cbf45dde2b49 257 char cFlags[] = {'\0', '\0', '\0'}, a[1];
HBP 0:cbf45dde2b49 258
HBP 0:cbf45dde2b49 259 if (createLabel >= 1)
HBP 0:cbf45dde2b49 260 {
HBP 0:cbf45dde2b49 261 // Write Volume label
HBP 0:cbf45dde2b49 262 cFlags[0] = '\x0E';
HBP 0:cbf45dde2b49 263 mem->write(a, iAddr, 3);
HBP 0:cbf45dde2b49 264 iAddr = BS;
HBP 0:cbf45dde2b49 265 i = 1;
HBP 0:cbf45dde2b49 266 }
HBP 0:cbf45dde2b49 267
HBP 0:cbf45dde2b49 268 cFlags[0] = '\x04';
HBP 0:cbf45dde2b49 269 for (; i < BC; i++)
HBP 0:cbf45dde2b49 270 {
HBP 0:cbf45dde2b49 271 mem->write(cFlags, iAddr, 3);
HBP 0:cbf45dde2b49 272 mem->read(iAddr, 1, a);
HBP 0:cbf45dde2b49 273 if (a[0] != cFlags[0])
HBP 0:cbf45dde2b49 274 bad++;
HBP 0:cbf45dde2b49 275 iAddr += BS;
HBP 0:cbf45dde2b49 276 }
HBP 0:cbf45dde2b49 277
HBP 0:cbf45dde2b49 278 return bad;
HBP 0:cbf45dde2b49 279 }
HBP 0:cbf45dde2b49 280
HBP 0:cbf45dde2b49 281 file::file(mfs *fs_ref, char filename[20], char operation)
HBP 0:cbf45dde2b49 282 {
HBP 0:cbf45dde2b49 283 // Operations:
HBP 9:52c01cb100ac 284 // 0 = Open in RO
HBP 9:52c01cb100ac 285 // 1 = Open in RW
HBP 0:cbf45dde2b49 286 attr = operation;
HBP 0:cbf45dde2b49 287
HBP 0:cbf45dde2b49 288 fs = fs_ref; // Don't forget this :)
HBP 0:cbf45dde2b49 289
HBP 9:52c01cb100ac 290 uint32_t n;
HBP 0:cbf45dde2b49 291 char cData[3] = {'\0','\0','\0'};
HBP 0:cbf45dde2b49 292
HBP 0:cbf45dde2b49 293 // Check if file exists
HBP 0:cbf45dde2b49 294 n = fs->getFirstBlockOfFile(filename);
HBP 0:cbf45dde2b49 295 if (n == 0xFFFF)
HBP 0:cbf45dde2b49 296 error("Oops, file \"%s\" not found! n=0x%X", filename, n); // File not found
HBP 0:cbf45dde2b49 297
HBP 0:cbf45dde2b49 298 fs->read(cData, n, 0, 1);
HBP 0:cbf45dde2b49 299 char flags = (cData[0] & 0x01)|((cData[0] & 0x10) >> 3)|((cData[0] & 0x20) >> 3);
HBP 0:cbf45dde2b49 300
HBP 0:cbf45dde2b49 301 if (attr == 1)
HBP 0:cbf45dde2b49 302 {
HBP 0:cbf45dde2b49 303 if ((flags & 0x04) != 0)
HBP 0:cbf45dde2b49 304 error("Oops, cant open in RW mode!");
HBP 0:cbf45dde2b49 305 }
HBP 0:cbf45dde2b49 306
HBP 0:cbf45dde2b49 307 // Store FBOF number
HBP 0:cbf45dde2b49 308 firstBlock = n;
HBP 0:cbf45dde2b49 309 currBlock = n;
HBP 0:cbf45dde2b49 310 blockPos = RB+20; // skip flags + pointers + filename
HBP 0:cbf45dde2b49 311
HBP 0:cbf45dde2b49 312 // Initialize buffer
HBP 0:cbf45dde2b49 313 for (unsigned int i=0; i < BUF; i++)
HBP 0:cbf45dde2b49 314 buffer[i] = '\0';
HBP 0:cbf45dde2b49 315 bufPos = 0;
HBP 0:cbf45dde2b49 316 }
HBP 0:cbf45dde2b49 317
HBP 0:cbf45dde2b49 318 file::~file()
HBP 0:cbf45dde2b49 319 {
HBP 0:cbf45dde2b49 320 flush();
HBP 0:cbf45dde2b49 321 }
HBP 0:cbf45dde2b49 322
HBP 0:cbf45dde2b49 323 void file::rewind()
HBP 0:cbf45dde2b49 324 {
HBP 0:cbf45dde2b49 325 flush();
HBP 0:cbf45dde2b49 326 currBlock = firstBlock;
HBP 0:cbf45dde2b49 327 blockPos = RB+20; // skip flags & pointers + filename
HBP 0:cbf45dde2b49 328 }
HBP 0:cbf45dde2b49 329
HBP 9:52c01cb100ac 330 char file::rewind(uint32_t n)
HBP 5:a0fe74dce80d 331 {
HBP 9:52c01cb100ac 332 uint32_t i;
HBP 5:a0fe74dce80d 333 char cData[3];
HBP 5:a0fe74dce80d 334
HBP 9:52c01cb100ac 335 flush(); // Check if flush is needed
HBP 5:a0fe74dce80d 336
HBP 5:a0fe74dce80d 337 for (i=0; i < n; i++)
HBP 5:a0fe74dce80d 338 {
HBP 5:a0fe74dce80d 339 blockPos--;
HBP 5:a0fe74dce80d 340
HBP 5:a0fe74dce80d 341 // Change Block?
HBP 5:a0fe74dce80d 342 if (blockPos < 3)
HBP 5:a0fe74dce80d 343 {
HBP 5:a0fe74dce80d 344 // Fetch link to next block
HBP 5:a0fe74dce80d 345 fs->read(cData, currBlock, 0, 3);
HBP 5:a0fe74dce80d 346 if (!(cData[0] & 0x80))
HBP 5:a0fe74dce80d 347 {
HBP 5:a0fe74dce80d 348 currBlock = cData[2];
HBP 5:a0fe74dce80d 349 blockPos = BS-1; // Set block postion offset at end of the block
HBP 5:a0fe74dce80d 350 } else {
HBP 5:a0fe74dce80d 351 blockPos++;
HBP 5:a0fe74dce80d 352 return 1; // This is the last block
HBP 5:a0fe74dce80d 353 }
HBP 5:a0fe74dce80d 354 }
HBP 5:a0fe74dce80d 355 fs->read(cData, currBlock, blockPos, 1);
HBP 5:a0fe74dce80d 356 if (cData[0] == mEOF)
HBP 5:a0fe74dce80d 357 return 1;
HBP 5:a0fe74dce80d 358 }
HBP 5:a0fe74dce80d 359
HBP 5:a0fe74dce80d 360 return 0; // OK
HBP 5:a0fe74dce80d 361 }
HBP 5:a0fe74dce80d 362
HBP 0:cbf45dde2b49 363 char file::forward()
HBP 0:cbf45dde2b49 364 {
HBP 5:a0fe74dce80d 365 return forward(1);
HBP 5:a0fe74dce80d 366 }
HBP 5:a0fe74dce80d 367
HBP 9:52c01cb100ac 368 char file::forward(uint32_t n)
HBP 5:a0fe74dce80d 369 {
HBP 9:52c01cb100ac 370 uint32_t i;
HBP 0:cbf45dde2b49 371 char cData[2];
HBP 0:cbf45dde2b49 372
HBP 9:52c01cb100ac 373 flush(); // Check if flush is needed
HBP 5:a0fe74dce80d 374
HBP 5:a0fe74dce80d 375 for (i=0; i < n; i++)
HBP 5:a0fe74dce80d 376 {
HBP 5:a0fe74dce80d 377 blockPos++;
HBP 0:cbf45dde2b49 378
HBP 5:a0fe74dce80d 379 // Change Block?
HBP 5:a0fe74dce80d 380 if (blockPos > BS-1)
HBP 5:a0fe74dce80d 381 {
HBP 5:a0fe74dce80d 382 // Fetch link to next block
HBP 5:a0fe74dce80d 383 fs->read(cData, currBlock, 0, 2);
HBP 5:a0fe74dce80d 384 if (!(cData[0] & 0x40))
HBP 5:a0fe74dce80d 385 {
HBP 5:a0fe74dce80d 386 currBlock = cData[1];
HBP 5:a0fe74dce80d 387 blockPos = RB; // Reset block position offset
HBP 5:a0fe74dce80d 388 } else {
HBP 5:a0fe74dce80d 389 blockPos--;
HBP 5:a0fe74dce80d 390 return 1; // This is the last block
HBP 5:a0fe74dce80d 391 }
HBP 5:a0fe74dce80d 392 }
HBP 5:a0fe74dce80d 393 fs->read(cData, currBlock, blockPos, 1);
HBP 5:a0fe74dce80d 394 if (cData[0] == mEOF)
HBP 5:a0fe74dce80d 395 return 1;
HBP 5:a0fe74dce80d 396 }
HBP 0:cbf45dde2b49 397
HBP 0:cbf45dde2b49 398 return 0; // OK
HBP 0:cbf45dde2b49 399 }
HBP 0:cbf45dde2b49 400
HBP 0:cbf45dde2b49 401 // Respects mEOF and automatically sets '\0' at the end of string
HBP 9:52c01cb100ac 402 void file::read(char *data, uint32_t n)
HBP 0:cbf45dde2b49 403 {
HBP 9:52c01cb100ac 404 uint32_t i;
HBP 0:cbf45dde2b49 405 char cData[2];
HBP 0:cbf45dde2b49 406
HBP 9:52c01cb100ac 407 flush();
HBP 0:cbf45dde2b49 408
HBP 0:cbf45dde2b49 409 for (i=0; i < n; i++)
HBP 0:cbf45dde2b49 410 {
HBP 0:cbf45dde2b49 411 // Change block?
HBP 0:cbf45dde2b49 412 if (blockPos == BS-1)
HBP 0:cbf45dde2b49 413 {
HBP 0:cbf45dde2b49 414 // Fetch link to next block
HBP 0:cbf45dde2b49 415 fs->read(cData, currBlock, 0, 2);
HBP 0:cbf45dde2b49 416 if (!(cData[0] & 0x40))
HBP 0:cbf45dde2b49 417 {
HBP 0:cbf45dde2b49 418 currBlock = cData[1];
HBP 0:cbf45dde2b49 419 blockPos = RB; // Reset block position offset
HBP 0:cbf45dde2b49 420 } else goto stop;
HBP 0:cbf45dde2b49 421 }
HBP 0:cbf45dde2b49 422
HBP 0:cbf45dde2b49 423 // Read data
HBP 0:cbf45dde2b49 424 fs->read(cData, currBlock, blockPos, 1);
HBP 0:cbf45dde2b49 425 if (cData[0] == mEOF)
HBP 0:cbf45dde2b49 426 {
HBP 0:cbf45dde2b49 427 stop:
HBP 0:cbf45dde2b49 428 data[i]='\0';
HBP 0:cbf45dde2b49 429 return;
HBP 5:a0fe74dce80d 430 } else {
HBP 5:a0fe74dce80d 431 data[i] = cData[0];
HBP 5:a0fe74dce80d 432 blockPos++;
HBP 5:a0fe74dce80d 433 }
HBP 0:cbf45dde2b49 434 }
HBP 5:a0fe74dce80d 435 if (data[i] != '\0')
HBP 5:a0fe74dce80d 436 data[i] = '\0';
HBP 0:cbf45dde2b49 437 }
HBP 0:cbf45dde2b49 438
HBP 0:cbf45dde2b49 439 // Ignores mEOF and doesn't set '\0' markings
HBP 9:52c01cb100ac 440 void file::readBin(char *data, uint32_t n)
HBP 0:cbf45dde2b49 441 {
HBP 9:52c01cb100ac 442 uint32_t i;
HBP 0:cbf45dde2b49 443 char cData[2];
HBP 0:cbf45dde2b49 444
HBP 0:cbf45dde2b49 445 for (i=0; i < n; i++)
HBP 0:cbf45dde2b49 446 {
HBP 0:cbf45dde2b49 447 // Change block?
HBP 0:cbf45dde2b49 448 if (blockPos == BS-1)
HBP 0:cbf45dde2b49 449 {
HBP 0:cbf45dde2b49 450 // Fetch link to next block
HBP 0:cbf45dde2b49 451 fs->read(cData, currBlock, 0, 2);
HBP 0:cbf45dde2b49 452 if (!(cData[0] & 0x40))
HBP 0:cbf45dde2b49 453 {
HBP 0:cbf45dde2b49 454 currBlock = cData[1];
HBP 0:cbf45dde2b49 455 blockPos = RB; // Reset block position offset
HBP 0:cbf45dde2b49 456 } else return;
HBP 0:cbf45dde2b49 457 }
HBP 0:cbf45dde2b49 458
HBP 0:cbf45dde2b49 459 // Read data
HBP 0:cbf45dde2b49 460 fs->read(cData, currBlock, blockPos, 1);
HBP 0:cbf45dde2b49 461 data[i] = cData[0];
HBP 0:cbf45dde2b49 462
HBP 0:cbf45dde2b49 463 blockPos++;
HBP 0:cbf45dde2b49 464 }
HBP 0:cbf45dde2b49 465 data[i-1] = '\0';
HBP 0:cbf45dde2b49 466 }
HBP 0:cbf45dde2b49 467
HBP 0:cbf45dde2b49 468 // Always binary
HBP 9:52c01cb100ac 469 char file::write(char *data, uint32_t n)
HBP 0:cbf45dde2b49 470 {
HBP 0:cbf45dde2b49 471 if (attr == 0) return 1;
HBP 0:cbf45dde2b49 472
HBP 9:52c01cb100ac 473 for (uint32_t i=0; i < n; i++)
HBP 0:cbf45dde2b49 474 {
HBP 0:cbf45dde2b49 475 // write to the buffer
HBP 0:cbf45dde2b49 476 buffer[bufPos] = data[i];
HBP 0:cbf45dde2b49 477 bufPos++;
HBP 0:cbf45dde2b49 478
HBP 0:cbf45dde2b49 479 // If the buffer is full then flush
HBP 0:cbf45dde2b49 480 if(bufPos == BUF)
HBP 0:cbf45dde2b49 481 {
HBP 0:cbf45dde2b49 482 if(flush() != 0);
HBP 0:cbf45dde2b49 483 return 1; // Flush failed
HBP 0:cbf45dde2b49 484 }
HBP 0:cbf45dde2b49 485 }
HBP 0:cbf45dde2b49 486
HBP 0:cbf45dde2b49 487 return 0;
HBP 0:cbf45dde2b49 488 }
HBP 0:cbf45dde2b49 489
HBP 0:cbf45dde2b49 490 char file::flush()
HBP 0:cbf45dde2b49 491 {
HBP 0:cbf45dde2b49 492 char cData[3], c[1];
HBP 0:cbf45dde2b49 493 char nextFree;
HBP 9:52c01cb100ac 494 uint32_t i;
HBP 0:cbf45dde2b49 495
HBP 0:cbf45dde2b49 496 if (bufPos == 0) return 0; // File up-to date
HBP 0:cbf45dde2b49 497 if (attr == 0) return 1;
HBP 0:cbf45dde2b49 498
HBP 0:cbf45dde2b49 499 for (i=0; i < bufPos; i++)
HBP 0:cbf45dde2b49 500 {
HBP 0:cbf45dde2b49 501 if(i%2)
HBP 0:cbf45dde2b49 502 FlushLed = 1;
HBP 0:cbf45dde2b49 503 else
HBP 0:cbf45dde2b49 504 FlushLed = 0;
HBP 0:cbf45dde2b49 505
HBP 0:cbf45dde2b49 506 // Change Block?
HBP 0:cbf45dde2b49 507 if (blockPos >= BS-2) // Must left space for mEOF
HBP 0:cbf45dde2b49 508 {
HBP 0:cbf45dde2b49 509 // Fetch new unused block number
HBP 0:cbf45dde2b49 510 if(fs->getNextFreeBlock(&nextFree) != 0)
HBP 0:cbf45dde2b49 511 return 1;
HBP 0:cbf45dde2b49 512
HBP 9:52c01cb100ac 513 // Take new block into use
HBP 9:52c01cb100ac 514 cData[0] = 0x4C; // New flags
HBP 9:52c01cb100ac 515 cData[1] = '\0';
HBP 9:52c01cb100ac 516 cData[2] = currBlock; // Prev Block
HBP 9:52c01cb100ac 517 fs->write(cData, nextFree, 0, 3); // Update Block Data
HBP 9:52c01cb100ac 518
HBP 0:cbf45dde2b49 519 // Link old block with new block
HBP 0:cbf45dde2b49 520 fs->read(cData, currBlock, 0, 3);
HBP 0:cbf45dde2b49 521 cData[0] &= ~0x40; // Clear LBOF flag if set
HBP 0:cbf45dde2b49 522 cData[1] = nextFree;
HBP 0:cbf45dde2b49 523 cData[2] = '\0';
HBP 0:cbf45dde2b49 524 fs->write(cData, currBlock, 0, 3); // Update Block Data
HBP 0:cbf45dde2b49 525
HBP 9:52c01cb100ac 526 // Update current block info
HBP 9:52c01cb100ac 527 currBlock = nextFree;
HBP 0:cbf45dde2b49 528 blockPos = RB; // Reset block position offset
HBP 9:52c01cb100ac 529
HBP 0:cbf45dde2b49 530 }
HBP 0:cbf45dde2b49 531
HBP 0:cbf45dde2b49 532 if (blockPos < 3)
HBP 0:cbf45dde2b49 533 error("");
HBP 0:cbf45dde2b49 534
HBP 0:cbf45dde2b49 535 // Write file
HBP 0:cbf45dde2b49 536 c[0]=buffer[i];
HBP 0:cbf45dde2b49 537 fs->write(c, currBlock, blockPos, 1);
HBP 0:cbf45dde2b49 538 blockPos++;
HBP 0:cbf45dde2b49 539 }
HBP 0:cbf45dde2b49 540 // Write mEOF
HBP 0:cbf45dde2b49 541 fs->write((char[]){mEOF}, currBlock, blockPos+1, 1);
HBP 0:cbf45dde2b49 542
HBP 0:cbf45dde2b49 543 bufPos = 0; // Reset buffer position counter
HBP 0:cbf45dde2b49 544
HBP 0:cbf45dde2b49 545 FlushLed = 0;
HBP 0:cbf45dde2b49 546 return 0;
HBP 0:cbf45dde2b49 547 }