mFS file system library for EEPROM memory chips.

Committer:
HBP
Date:
Mon Feb 21 07:35:16 2011 +0000
Revision:
0:cbf45dde2b49
Child:
5:a0fe74dce80d
Initial release

Who changed what in which revision?

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