mFS file system library for EEPROM memory chips.

Committer:
HBP
Date:
Mon Feb 21 22:37:00 2011 +0000
Revision:
7:5ac5121bb4e0
Parent:
5:a0fe74dce80d
Child:
9:52c01cb100ac
File rename function

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