mFS file system library for EEPROM memory chips.

Committer:
HBP
Date:
Tue Feb 22 21:09:04 2011 +0000
Revision:
10:211cb54339a0
Parent:
9:52c01cb100ac
Child:
11:6c4fcb9d6193
Code optimizations and improvements in documentation

Who changed what in which revision?

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