mFS file system library for EEPROM memory chips.

Committer:
HBP
Date:
Mon Feb 21 18:26:27 2011 +0000
Revision:
5:a0fe74dce80d
Parent:
0:cbf45dde2b49
Child:
7:5ac5121bb4e0
-File::read issues fixed
-rewind/forward functions improved
-Added possibility change I2C speed
-I2C autoreset on failure (P20 wired to SCL)

Now it\s actually realible and useful library :)

Who changed what in which revision?

UserRevisionLine numberNew contents of line
HBP 5:a0fe74dce80d 1 /*CPP**************************************************************************
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 5:a0fe74dce80d 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 0:cbf45dde2b49 189 char mfs::setFileFlags(char *flags, char filename[20])
HBP 0:cbf45dde2b49 190 {
HBP 0:cbf45dde2b49 191 /* RO|HIDDEN|LOCK *
HBP 0:cbf45dde2b49 192 * H L */
HBP 0:cbf45dde2b49 193
HBP 0:cbf45dde2b49 194 uint16 n;
HBP 0:cbf45dde2b49 195 char cData[1] = {'\0'};
HBP 0:cbf45dde2b49 196
HBP 0:cbf45dde2b49 197 // Check if file exists
HBP 0:cbf45dde2b49 198 n = getFirstBlockOfFile(filename);
HBP 0:cbf45dde2b49 199 if (n > BC)
HBP 0:cbf45dde2b49 200 return 1; // File not found
HBP 0:cbf45dde2b49 201
HBP 0:cbf45dde2b49 202 read(cData, n, 0, 1);
HBP 0:cbf45dde2b49 203 cData[0] |= (flags[0] & 0x01)|((flags[0] & 0x02) << 3)|((flags[0] & 0x04) << 3);
HBP 0:cbf45dde2b49 204 write(cData, n, 0, 1);
HBP 0:cbf45dde2b49 205
HBP 0:cbf45dde2b49 206 return 0;
HBP 0:cbf45dde2b49 207 }
HBP 0:cbf45dde2b49 208
HBP 0:cbf45dde2b49 209 char mfs::getFileFlags(char *flags, char filename[20])
HBP 0:cbf45dde2b49 210 {
HBP 0:cbf45dde2b49 211 /* RO|HIDDEN|LOCK *
HBP 0:cbf45dde2b49 212 * H L */
HBP 0:cbf45dde2b49 213
HBP 0:cbf45dde2b49 214 uint16 n;
HBP 0:cbf45dde2b49 215 char cData[1] = {'\0'};
HBP 0:cbf45dde2b49 216
HBP 0:cbf45dde2b49 217 // Check if file exists
HBP 0:cbf45dde2b49 218 n = getFirstBlockOfFile(filename);
HBP 0:cbf45dde2b49 219 if (n > BC)
HBP 0:cbf45dde2b49 220 return 1; // File not found
HBP 0:cbf45dde2b49 221
HBP 0:cbf45dde2b49 222 read(cData, n, 0, 1);
HBP 0:cbf45dde2b49 223 flags[0] = (cData[0] & 0x01)|((cData[0] & 0x10) >> 3)|((cData[0] & 0x20) >> 3);
HBP 0:cbf45dde2b49 224
HBP 0:cbf45dde2b49 225 return 0;
HBP 0:cbf45dde2b49 226 }
HBP 0:cbf45dde2b49 227
HBP 0:cbf45dde2b49 228 // Return number of free blocks
HBP 0:cbf45dde2b49 229 uint16 mfs::free()
HBP 0:cbf45dde2b49 230 {
HBP 0:cbf45dde2b49 231 uint16 blocks=0;
HBP 0:cbf45dde2b49 232 uint16 r;
HBP 0:cbf45dde2b49 233 char cFlags[1];
HBP 0:cbf45dde2b49 234
HBP 0:cbf45dde2b49 235 for (r=0; r < BC; r++)
HBP 0:cbf45dde2b49 236 {
HBP 0:cbf45dde2b49 237 read(cFlags, r, 0, 1);
HBP 0:cbf45dde2b49 238 if (cFlags[0] == 0x04)
HBP 0:cbf45dde2b49 239 blocks++;
HBP 0:cbf45dde2b49 240 if (r >= BC-1)
HBP 0:cbf45dde2b49 241 return blocks;
HBP 0:cbf45dde2b49 242 }
HBP 0:cbf45dde2b49 243
HBP 0:cbf45dde2b49 244 return 0;
HBP 0:cbf45dde2b49 245 }
HBP 0:cbf45dde2b49 246
HBP 0:cbf45dde2b49 247 char mfs::mkfs(char createLabel)
HBP 0:cbf45dde2b49 248 {
HBP 0:cbf45dde2b49 249 unsigned int iAddr = 0;
HBP 0:cbf45dde2b49 250 uint16 i = 0;
HBP 0:cbf45dde2b49 251 uint16 bad = 0; // For counting bad block headers
HBP 0:cbf45dde2b49 252 char cFlags[] = {'\0', '\0', '\0'}, a[1];
HBP 0:cbf45dde2b49 253
HBP 0:cbf45dde2b49 254 if (createLabel >= 1)
HBP 0:cbf45dde2b49 255 {
HBP 0:cbf45dde2b49 256 // Write Volume label
HBP 0:cbf45dde2b49 257 cFlags[0] = '\x0E';
HBP 0:cbf45dde2b49 258 mem->write(a, iAddr, 3);
HBP 0:cbf45dde2b49 259 iAddr = BS;
HBP 0:cbf45dde2b49 260 i = 1;
HBP 0:cbf45dde2b49 261 }
HBP 0:cbf45dde2b49 262
HBP 0:cbf45dde2b49 263 cFlags[0] = '\x04';
HBP 0:cbf45dde2b49 264 for (; i < BC; i++)
HBP 0:cbf45dde2b49 265 {
HBP 0:cbf45dde2b49 266 mem->write(cFlags, iAddr, 3);
HBP 0:cbf45dde2b49 267 mem->read(iAddr, 1, a);
HBP 0:cbf45dde2b49 268 if (a[0] != cFlags[0])
HBP 0:cbf45dde2b49 269 bad++;
HBP 0:cbf45dde2b49 270 iAddr += BS;
HBP 0:cbf45dde2b49 271 }
HBP 0:cbf45dde2b49 272
HBP 0:cbf45dde2b49 273 return bad;
HBP 0:cbf45dde2b49 274 }
HBP 0:cbf45dde2b49 275
HBP 0:cbf45dde2b49 276 file::file(mfs *fs_ref, char filename[20], char operation)
HBP 0:cbf45dde2b49 277 {
HBP 0:cbf45dde2b49 278 // Operations:
HBP 0:cbf45dde2b49 279 // 0 = Open RO
HBP 0:cbf45dde2b49 280 // 1 = Open RW
HBP 0:cbf45dde2b49 281 attr = operation;
HBP 0:cbf45dde2b49 282
HBP 0:cbf45dde2b49 283 fs = fs_ref; // Don't forget this :)
HBP 0:cbf45dde2b49 284
HBP 0:cbf45dde2b49 285 uint16 n;
HBP 0:cbf45dde2b49 286 char cData[3] = {'\0','\0','\0'};
HBP 0:cbf45dde2b49 287
HBP 0:cbf45dde2b49 288 // Check if file exists
HBP 0:cbf45dde2b49 289 n = fs->getFirstBlockOfFile(filename);
HBP 0:cbf45dde2b49 290 if (n == 0xFFFF)
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::needsFlush()
HBP 0:cbf45dde2b49 319 {
HBP 0:cbf45dde2b49 320 if (bufPos > 0)
HBP 0:cbf45dde2b49 321 {
HBP 0:cbf45dde2b49 322 char tmpBlock = currBlock;
HBP 0:cbf45dde2b49 323 unsigned int tmpPos = blockPos;
HBP 0:cbf45dde2b49 324
HBP 0:cbf45dde2b49 325 if(flush() != 0)
HBP 0:cbf45dde2b49 326 error("Flush failed!");
HBP 0:cbf45dde2b49 327 currBlock = tmpBlock;
HBP 0:cbf45dde2b49 328 blockPos = tmpPos;
HBP 0:cbf45dde2b49 329 }
HBP 0:cbf45dde2b49 330 }
HBP 0:cbf45dde2b49 331
HBP 0:cbf45dde2b49 332 void file::rewind()
HBP 0:cbf45dde2b49 333 {
HBP 0:cbf45dde2b49 334 flush();
HBP 0:cbf45dde2b49 335 currBlock = firstBlock;
HBP 0:cbf45dde2b49 336 blockPos = RB+20; // skip flags & pointers + filename
HBP 0:cbf45dde2b49 337 }
HBP 0:cbf45dde2b49 338
HBP 5:a0fe74dce80d 339 char file::rewind(uint16 n)
HBP 5:a0fe74dce80d 340 {
HBP 5:a0fe74dce80d 341 uint16 i;
HBP 5:a0fe74dce80d 342 char cData[3];
HBP 5:a0fe74dce80d 343
HBP 5:a0fe74dce80d 344 needsFlush(); // Check if flush is needed
HBP 5:a0fe74dce80d 345
HBP 5:a0fe74dce80d 346 for (i=0; i < n; i++)
HBP 5:a0fe74dce80d 347 {
HBP 5:a0fe74dce80d 348 blockPos--;
HBP 5:a0fe74dce80d 349
HBP 5:a0fe74dce80d 350 // Change Block?
HBP 5:a0fe74dce80d 351 if (blockPos < 3)
HBP 5:a0fe74dce80d 352 {
HBP 5:a0fe74dce80d 353 // Fetch link to next block
HBP 5:a0fe74dce80d 354 fs->read(cData, currBlock, 0, 3);
HBP 5:a0fe74dce80d 355 if (!(cData[0] & 0x80))
HBP 5:a0fe74dce80d 356 {
HBP 5:a0fe74dce80d 357 currBlock = cData[2];
HBP 5:a0fe74dce80d 358 blockPos = BS-1; // Set block postion offset at end of the block
HBP 5:a0fe74dce80d 359 } else {
HBP 5:a0fe74dce80d 360 blockPos++;
HBP 5:a0fe74dce80d 361 return 1; // This is the last block
HBP 5:a0fe74dce80d 362 }
HBP 5:a0fe74dce80d 363 }
HBP 5:a0fe74dce80d 364 fs->read(cData, currBlock, blockPos, 1);
HBP 5:a0fe74dce80d 365 if (cData[0] == mEOF)
HBP 5:a0fe74dce80d 366 return 1;
HBP 5:a0fe74dce80d 367 }
HBP 5:a0fe74dce80d 368
HBP 5:a0fe74dce80d 369 return 0; // OK
HBP 5:a0fe74dce80d 370 }
HBP 5:a0fe74dce80d 371
HBP 0:cbf45dde2b49 372 char file::forward()
HBP 0:cbf45dde2b49 373 {
HBP 5:a0fe74dce80d 374 return forward(1);
HBP 5:a0fe74dce80d 375 }
HBP 5:a0fe74dce80d 376
HBP 5:a0fe74dce80d 377 char file::forward(uint16 n)
HBP 5:a0fe74dce80d 378 {
HBP 5:a0fe74dce80d 379 uint16 i;
HBP 0:cbf45dde2b49 380 char cData[2];
HBP 0:cbf45dde2b49 381
HBP 5:a0fe74dce80d 382 needsFlush(); // Check if flush is needed
HBP 5:a0fe74dce80d 383
HBP 5:a0fe74dce80d 384 for (i=0; i < n; i++)
HBP 5:a0fe74dce80d 385 {
HBP 5:a0fe74dce80d 386 blockPos++;
HBP 0:cbf45dde2b49 387
HBP 5:a0fe74dce80d 388 // Change Block?
HBP 5:a0fe74dce80d 389 if (blockPos > BS-1)
HBP 5:a0fe74dce80d 390 {
HBP 5:a0fe74dce80d 391 // Fetch link to next block
HBP 5:a0fe74dce80d 392 fs->read(cData, currBlock, 0, 2);
HBP 5:a0fe74dce80d 393 if (!(cData[0] & 0x40))
HBP 5:a0fe74dce80d 394 {
HBP 5:a0fe74dce80d 395 currBlock = cData[1];
HBP 5:a0fe74dce80d 396 blockPos = RB; // Reset block position offset
HBP 5:a0fe74dce80d 397 } else {
HBP 5:a0fe74dce80d 398 blockPos--;
HBP 5:a0fe74dce80d 399 return 1; // This is the last block
HBP 5:a0fe74dce80d 400 }
HBP 5:a0fe74dce80d 401 }
HBP 5:a0fe74dce80d 402 fs->read(cData, currBlock, blockPos, 1);
HBP 5:a0fe74dce80d 403 if (cData[0] == mEOF)
HBP 5:a0fe74dce80d 404 return 1;
HBP 5:a0fe74dce80d 405 }
HBP 0:cbf45dde2b49 406
HBP 0:cbf45dde2b49 407 return 0; // OK
HBP 0:cbf45dde2b49 408 }
HBP 0:cbf45dde2b49 409
HBP 0:cbf45dde2b49 410 // Respects mEOF and automatically sets '\0' at the end of string
HBP 0:cbf45dde2b49 411 void file::read(char *data, unsigned int n)
HBP 0:cbf45dde2b49 412 {
HBP 0:cbf45dde2b49 413 unsigned int i;
HBP 0:cbf45dde2b49 414 char cData[2];
HBP 0:cbf45dde2b49 415
HBP 0:cbf45dde2b49 416 needsFlush();
HBP 0:cbf45dde2b49 417
HBP 0:cbf45dde2b49 418 for (i=0; i < n; i++)
HBP 0:cbf45dde2b49 419 {
HBP 0:cbf45dde2b49 420 // Change block?
HBP 0:cbf45dde2b49 421 if (blockPos == BS-1)
HBP 0:cbf45dde2b49 422 {
HBP 0:cbf45dde2b49 423 // Fetch link to next block
HBP 0:cbf45dde2b49 424 fs->read(cData, currBlock, 0, 2);
HBP 0:cbf45dde2b49 425 if (!(cData[0] & 0x40))
HBP 0:cbf45dde2b49 426 {
HBP 0:cbf45dde2b49 427 currBlock = cData[1];
HBP 0:cbf45dde2b49 428 blockPos = RB; // Reset block position offset
HBP 0:cbf45dde2b49 429 } else goto stop;
HBP 0:cbf45dde2b49 430 }
HBP 0:cbf45dde2b49 431
HBP 0:cbf45dde2b49 432 // Read data
HBP 0:cbf45dde2b49 433 fs->read(cData, currBlock, blockPos, 1);
HBP 0:cbf45dde2b49 434 if (cData[0] == mEOF)
HBP 0:cbf45dde2b49 435 {
HBP 0:cbf45dde2b49 436 stop:
HBP 0:cbf45dde2b49 437 data[i]='\0';
HBP 0:cbf45dde2b49 438 return;
HBP 5:a0fe74dce80d 439 } else {
HBP 5:a0fe74dce80d 440 data[i] = cData[0];
HBP 5:a0fe74dce80d 441 blockPos++;
HBP 5:a0fe74dce80d 442 }
HBP 0:cbf45dde2b49 443 }
HBP 5:a0fe74dce80d 444 if (data[i] != '\0')
HBP 5:a0fe74dce80d 445 data[i] = '\0';
HBP 0:cbf45dde2b49 446 }
HBP 0:cbf45dde2b49 447
HBP 0:cbf45dde2b49 448 // Ignores mEOF and doesn't set '\0' markings
HBP 0:cbf45dde2b49 449 void file::readBin(char *data, unsigned int n)
HBP 0:cbf45dde2b49 450 {
HBP 0:cbf45dde2b49 451 unsigned int i;
HBP 0:cbf45dde2b49 452 char cData[2];
HBP 0:cbf45dde2b49 453
HBP 0:cbf45dde2b49 454 for (i=0; i < n; i++)
HBP 0:cbf45dde2b49 455 {
HBP 0:cbf45dde2b49 456 // Change block?
HBP 0:cbf45dde2b49 457 if (blockPos == BS-1)
HBP 0:cbf45dde2b49 458 {
HBP 0:cbf45dde2b49 459 // Fetch link to next block
HBP 0:cbf45dde2b49 460 fs->read(cData, currBlock, 0, 2);
HBP 0:cbf45dde2b49 461 if (!(cData[0] & 0x40))
HBP 0:cbf45dde2b49 462 {
HBP 0:cbf45dde2b49 463 currBlock = cData[1];
HBP 0:cbf45dde2b49 464 blockPos = RB; // Reset block position offset
HBP 0:cbf45dde2b49 465 } else return;
HBP 0:cbf45dde2b49 466 }
HBP 0:cbf45dde2b49 467
HBP 0:cbf45dde2b49 468 // Read data
HBP 0:cbf45dde2b49 469 fs->read(cData, currBlock, blockPos, 1);
HBP 0:cbf45dde2b49 470 data[i] = cData[0];
HBP 0:cbf45dde2b49 471
HBP 0:cbf45dde2b49 472 blockPos++;
HBP 0:cbf45dde2b49 473 }
HBP 0:cbf45dde2b49 474 data[i-1] = '\0';
HBP 0:cbf45dde2b49 475 }
HBP 0:cbf45dde2b49 476
HBP 0:cbf45dde2b49 477 // Always binary
HBP 0:cbf45dde2b49 478 char file::write(char *data, unsigned int n)
HBP 0:cbf45dde2b49 479 {
HBP 0:cbf45dde2b49 480 if (attr == 0) return 1;
HBP 0:cbf45dde2b49 481
HBP 0:cbf45dde2b49 482 for (unsigned int i=0; i < n; i++)
HBP 0:cbf45dde2b49 483 {
HBP 0:cbf45dde2b49 484 // write to the buffer
HBP 0:cbf45dde2b49 485 buffer[bufPos] = data[i];
HBP 0:cbf45dde2b49 486 bufPos++;
HBP 0:cbf45dde2b49 487
HBP 0:cbf45dde2b49 488 // If the buffer is full then flush
HBP 0:cbf45dde2b49 489 if(bufPos == BUF)
HBP 0:cbf45dde2b49 490 {
HBP 0:cbf45dde2b49 491 if(flush() != 0);
HBP 0:cbf45dde2b49 492 return 1; // Flush failed
HBP 0:cbf45dde2b49 493 }
HBP 0:cbf45dde2b49 494 }
HBP 0:cbf45dde2b49 495
HBP 0:cbf45dde2b49 496 return 0;
HBP 0:cbf45dde2b49 497 }
HBP 0:cbf45dde2b49 498
HBP 0:cbf45dde2b49 499 char file::flush()
HBP 0:cbf45dde2b49 500 {
HBP 0:cbf45dde2b49 501 char cData[3], c[1];
HBP 0:cbf45dde2b49 502 char nextFree;
HBP 0:cbf45dde2b49 503 unsigned int i;
HBP 0:cbf45dde2b49 504
HBP 0:cbf45dde2b49 505 if (bufPos == 0) return 0; // File up-to date
HBP 0:cbf45dde2b49 506 if (attr == 0) return 1;
HBP 0:cbf45dde2b49 507
HBP 0:cbf45dde2b49 508 for (i=0; i < bufPos; i++)
HBP 0:cbf45dde2b49 509 {
HBP 0:cbf45dde2b49 510 if(i%2)
HBP 0:cbf45dde2b49 511 FlushLed = 1;
HBP 0:cbf45dde2b49 512 else
HBP 0:cbf45dde2b49 513 FlushLed = 0;
HBP 0:cbf45dde2b49 514
HBP 0:cbf45dde2b49 515 // Change Block?
HBP 0:cbf45dde2b49 516 if (blockPos >= BS-2) // Must left space for mEOF
HBP 0:cbf45dde2b49 517 {
HBP 0:cbf45dde2b49 518 // Fetch new unused block number
HBP 0:cbf45dde2b49 519 if(fs->getNextFreeBlock(&nextFree) != 0)
HBP 0:cbf45dde2b49 520 return 1;
HBP 0:cbf45dde2b49 521
HBP 0:cbf45dde2b49 522 // Link old block with new block
HBP 0:cbf45dde2b49 523 fs->read(cData, currBlock, 0, 3);
HBP 0:cbf45dde2b49 524 cData[0] &= ~0x40; // Clear LBOF flag if set
HBP 0:cbf45dde2b49 525 cData[1] = nextFree;
HBP 0:cbf45dde2b49 526 cData[2] = '\0';
HBP 0:cbf45dde2b49 527 fs->write(cData, currBlock, 0, 3); // Update Block Data
HBP 0:cbf45dde2b49 528
HBP 0:cbf45dde2b49 529 // Take new block into use
HBP 0:cbf45dde2b49 530 blockPos = RB; // Reset block position offset
HBP 0:cbf45dde2b49 531 cData[0] = 0x4C; // New flags
HBP 0:cbf45dde2b49 532 cData[1] = '\0';
HBP 0:cbf45dde2b49 533 cData[2] = currBlock; // Prev Block
HBP 0:cbf45dde2b49 534 currBlock = nextFree; // Change current block to new one
HBP 0:cbf45dde2b49 535 fs->write(cData, currBlock, 0, 3); // Update Block Data
HBP 0:cbf45dde2b49 536 }
HBP 0:cbf45dde2b49 537
HBP 0:cbf45dde2b49 538 if (blockPos < 3)
HBP 0:cbf45dde2b49 539 error("");
HBP 0:cbf45dde2b49 540
HBP 0:cbf45dde2b49 541 // Write file
HBP 0:cbf45dde2b49 542 c[0]=buffer[i];
HBP 0:cbf45dde2b49 543 fs->write(c, currBlock, blockPos, 1);
HBP 0:cbf45dde2b49 544 blockPos++;
HBP 0:cbf45dde2b49 545 }
HBP 0:cbf45dde2b49 546 // Write mEOF
HBP 0:cbf45dde2b49 547 fs->write((char[]){mEOF}, currBlock, blockPos+1, 1);
HBP 0:cbf45dde2b49 548
HBP 0:cbf45dde2b49 549 bufPos = 0; // Reset buffer position counter
HBP 0:cbf45dde2b49 550
HBP 0:cbf45dde2b49 551 FlushLed = 0;
HBP 0:cbf45dde2b49 552 return 0;
HBP 0:cbf45dde2b49 553 }