fl \ This is based fs.f. \ fs_128k - 128k-eeprom(24LC1025) file system \ \ A very simple file system for eeprom. The goal is not a general file system, but a place to put text \ (or code) in eeprom so it can be dynamically loaded by propforth \ \ the eeprom area start is defined by fsbot and the top is defined by fstop \ The files are in eeprom memory as such: \ 2 bytes - length of the contents of the file \ 1 byte - length of the file name (this is a normal counted string, counted strings can be up \ 255 bytes in length, the length here is limited for space reasons) \ 1 - 31 bytes - the file name \ 0 - 65534 bytes - the contents of the file \ \ the last file has a length of 65535 (0xFFFF) \ \ the start of every file is aligned with eeprom pages, for efficient read and write, this is 128 bytes \ \ Status: 26/08/2011 13:26:14 Beta \ \ \ main routines \ \ fsload filename - reads filename and directs it to the next free forth cog, every additional nested fsload \ requires an additional free cog \ fsread filename - reads the file and echos it directly to the terminal \ fswrite filename - writes the file to the filesystem - takes input from the input until ...\0x0d is encounterd \ - ie 3 dots followed by a carriage return \ fsls - lists the files \ fsclear - erases all files \ fsdrop - erases the last file \ \ \ The most common problem is forgetting the ...\x0d at the end of the file you want to write. Usually an fsdrop will \ erase the last file which is invalid. { Usage example: load this file type in fsclear load the contents below - select from the fl to 1 line past ... - need the last cr type in fsls - gives the list of the files type fsload demo - loads demo, which loads the other 3 files fl \ some simple files for testing fswrite demo fsload hello.f fsload bye.f fsload aloha.f ... fswrite hello.f \ hello ( --) : hello ." Hello world" cr ; ... fswrite bye.f \ bye ( --) : bye ." Goodbye world" cr ; ... fswrite aloha.f \ aloha ( t/f -- ) : aloha if ." Hello" else ." Goodbye" then ." world" cr ; ... \ end of example files } hex \ \ define only one of these, build_fsRO is useful when you want to be able to read files \ but want to make sure no-one can write them \ \ remember there are still eeprom write routines in the boot kernel \ so safety is not guaranteed \ 1 wconstant build_fs \ 1 wconstant build_fsRO \ constant ( x -- ) skip blanks parse the next word and create a constant, allocate a long, 4 bytes [ifndef constant : constant lockdict create $C_a_doconl w, l, forthentry freedict ; ] \ \ CONFIG PARAMETERS BEGIN \ { 24LC1025 address map B0 A1 A0 eeprom-address 0 0 0 00000 - 0ffff 1st eeprom Not use because there is prop eeprom 1 0 0 10000 - 1ffff 1st eeprom 0 0 1 20000 - 2ffff 2nd eeprom 1 0 1 30000 - 3ffff 2nd eeprom 0 1 0 40000 - 4ffff 3rd eeprom 1 1 0 50000 - 5ffff 3rd eeprom 0 1 1 60000 - 6ffff 4th eeprom 1 1 1 70000 - 7ffff 4th eeprom } 20000 constant fsbot \ the start adress in eeprom(24LC1025) for the file system 40000 constant fstop \ the end address in the eeprom(24LC1025) for th file system 80 wconstant fsps \ a page size which works with (64k8bit x 2) eeproms(24LC1025) \ \ CONFIG PARAMETERS END \ \ lasti? ( -- t/f ) true if this is the last value of i in this loop [ifndef lasti? : lasti? _rsptr COG@ 2+ COG@ 1- _rsptr COG@ 3 + COG@ = ; ] \ padbl ( -- ) fills this cogs pad with blanks [ifndef padbl : padbl pad padsize bl fill ; ] \ _eeread ( t/f -- c1 ) read a byte from the eeprom, ackbit in, byte out [ifndef _eeread : _eeread _sdai 0 8 0 do 1 lshift _sclh _sda? _scll if 1 or then loop swap if _sdah else _sdal then _sdao _sclh _scll _sdal ; ] \ ( eeAddr addr u -- eeAddr addr u ) make Block Select Bits from eeAddr : make_B0 rot dup 70000 and 10 rshift 2 u/mod drop if 8 else 0 then ; \ ( eeAddr addr u -- eeAddr addr ChipSelectBits ) send control-byte and address sequence to eeprom : make_control_byte 1 max rot dup ff and \ address low byte swap dup 8 rshift ff and \ address high byte swap 10 rshift 7 and 2 u/ 1 lshift \ A0 A1 ; \ ( eeAddr addr cotrol_byte -- eeAddr addr eeprom_ack ) : write_control_byte _eestart A0 or _eewrite \ write control byte swap _eewrite \ write address high byte or swap _eewrite \ write address low byte or ; \ the eereadpage and eewritePage words assume the eeprom are 128kx8 and will address up to \ 4 sequential eeproms \ eereadpage ( eeAddr addr u -- t/f ) return true if there was an error, use lock 1 \ eeAddr -- eeprom address \ addr -- buffer address \ u -- the number of bytes to read : eereadpage_128 make_B0 >r rot2 \ Block select bit 1lock make_control_byte r> or dup >r \ or B0 and A1/A0 write_control_byte \ write control byte _eestart r> A1 or _eewrite \ write control(read) byte or rot2 bounds do \ read u bytes from eeAddr to addr lasti? _eeread i C! loop _eestop 1unlock ; \ eewritepage_128 ( eeAddr addr u -- t/f ) return true if there was an error, use lock 1 : eewritepage_128 make_B0 >r rot2 \ Block select bit 1lock make_control_byte r> or \ or B0 and A1/A0 write_control_byte \ write control byte rot2 bounds do i C@ _eewrite or \ write data from addr in eeAddr loop _eestop 10 delms 1unlock ; \ EW!_128 ( n1 eeAddr -- ) : EW!_128 swap t0 W! t0 2 eewritepage_128 if A ERR then ; \ EW@_128 ( eeAddr -- n1 ) : EW@_128 t0 2 eereadpage_128 if B ERR then t0 W@ ; \ EC@_128 ( eeAddr -- c1 ) : EC@_128 EW@_128 FF and ; \ _fsk ( n1 -- n2) [ifndef _fsk : _fsk 8 lshift key or ; ] \ _fnf ( --) [ifndef _fnf : _fnf cr ." FILE NOT FOUND" cr ; ] \ (fspa) ( addr1 -- addr2) addr2 is the next page aligned address after addr1 : (fspa) fsps 1- + fsps 1- andn ; \ (fsnext) ( addr1 -- addr2 t/f) addr - the current file address, addr2 - the next addr, t/f - true if we have \ gone past the end of the eeprom. t0 -length of the current file \ t1 - length of the file name (char) : (fsnext) t0 W@ t1 C@ + 2+ 1+ + (fspa) dup fstop >= ; [ifndef build_fsRO \ (fswr) ( addr1 addr2 n1 -- ) addr1 - the eepropm address to write, addr2 - the address to write from \ n1 - the number of bytes to write : (fswr) dup >r rot dup r> + fstop 1- > if A ERR then rot2 eewritepage_128 if A ERR then ; ] \ (fsrd) ( addr1 addr2 n1 -- ) addr1 - the eepropm address to read, addr2 - the address of the read buffer \ n1 - the number of bytes to read : (fsrd) dup >r rot dup r> + fstop 1- > if ." error" B ERR then rot2 eereadpage_128 if ." Aerror" A ERR then ; \ (fsfree) ( -- n1 ) n1 is the first location in the file system, -1 if there are none : (fsfree) -1 fsbot begin \ read 3 bytes into t0, t1 and process dup t0 3 (fsrd) t0 W@ FFFF = if nip dup -1 else (fsnext) then until drop ; \ (fsfind) ( cstr -- addr ) find the last file named cstr, addr is the eeprom address, 0 if not found : (fsfind) fsbot 0 >r begin \ read namesizemax 1F + 3 bytes into t0, t1, and tbuf dup t0 22 (fsrd) t0 W@ FFFF = if -1 else over t1 cstr= if r> drop dup >r then (fsnext) then until 2drop r> ; \ (fslast) ( -- addr ) find the last file, 0 if not found : (fslast) 0 fsbot begin \ read namesizemax 1F + 3 bytes into t0, t1, and tbuf dup t0 22 (fsrd) t0 W@ FFFF = if -1 else nip dup (fsnext) then until drop ; [ifndef build_fsRO \ fsclr ( -- ) : fsclr padbl fsbot 400 + fsbot do i pad fsps (fswr) 2e emit fsps +loop -1 fsbot EW!_128 ; : fsclear -1 fsbot EW!_128 ; ] \ fsfree ( -- ) : fsfree (fsfree) dup -1 = if 0 else fstop swap - then cr . ." bytes free in EEPROM file system" cr ; \ fsls ( -- ) list the files : fsls cr fsbot begin \ read namesizemax 1F + 3 bytes into t0, t1, and tbuf dup t0 22 (fsrd) t0 W@ FFFF = if -1 else dup .long space t0 W@ .word space t1 .cstr cr (fsnext) then until drop fsfree ; \ (fsread) ( cstr -- ) : (fsread) (fsfind) dup if \ read 3 bytes into t0, t1 and process dup t0 3 (fsrd) t1 C@ + 2+ 1+ t0 W@ bounds do fsps 1- i and 0= ibound i - fsps >= and if i pad fsps (fsrd) pad fsps bounds do i C@ emit loop i fsps 1- + seti else i EC@_128 emit then loop else drop then padbl ; \ _fsp ( -- cstr ) filename, if cstr is 0 no file found : _fsp parsenw dup if dup (fsfind) 0= if drop 0 then then ; \ fsread ( -- ) filename : fsread _fsp dup if (fsread) else drop _fnf then ; \ (fsload) ( cstr -- ) : (fsload) cogid nfcog iolink (fsread) d emit d emit cogid iounlink ; \ fsload filename ( -- ) send the file to the next free forth cog : fsload _fsp dup if (fsload) else drop _fnf then ; [ifndef build_fsRO \ fswrite filename ( -- ) writes a file until ... followed immediately by a cr is encountered : fswrite (fsfree) dup -1 <> parsenw dup rot and if \ set the file length to 0, copy in the file name 0 pad W! dup C@ 2+ 1+ pad + swap pad 2+ ccopy \ find the first free page 0 swap key _fsk _fsk _fsk \ ( eaddr1 n1 addr2 n2 ) eaddr - start of file in the eeprom, n1 - bytes written so far, addr2 - next addr in the pad, \ n2 - a 4 byte key buffer begin \ check to see if we have a ... at the end of a line 2E2E2E0D over = if -1 else \ get a key from the key buffer, write it the the pad tuck 18 rshift dup dup d = if drop cr else emit then over C! 1+ tuck pad - fsps = if \ we have a page worth of data, write it out nip rot2 2dup + pad fsps (fswr) fsps + rot pad swap then \ get another key _fsk 0 then until \ any keys left? drop pad - dup 0> if \ write the leftover, not a full page >r 2dup + pad r> dup >r (fswr) r> + else drop then \ write the length of FFFF for the next file 2dup + FFFF swap (fspa) dup fstop 1- < if EW!_128 else 2drop then \ subtract the length of the filename +1, and the 2 bytes which are the length of the file, and update the length of the file over 2+ EC@_128 2+ 1+ - swap EW!_128 else 2drop clearkeys then padbl ; \ fsdrop ( -- ) deletes last file : fsdrop (fslast) dup -1 = if drop else FFFF swap EW!_128 then ; { \ dispay address and size : (dumpb) cr over .long space dup .word _ecs bounds ; : (dumpm) cr .long _ecs ; \ (dumpe) ( addr cnt -- ) uses tbuf : (dumpe) tbuf 10 bounds do i C@ .byte space loop 2 spaces tbuf 10 bounds do i C@ dup bl < if drop 2e then emit loop ; } \ edump ( addr cnt -- ) uses tbuf : edump (dumpb) do i (dumpm) i tbuf 10 eereadpage_128 if tbuf 10 0 fill then (dumpe) 10 +loop cr ; decimal