Re: FAT32 on Compact Flash project
Posted: Wed Jan 15, 2020 2:25 am
Now I can start implementing some of the ANS words. I checked the older ANS standards to see if there was anything "simpler", but it looks like the ANS2012 is a copy/paste of the ANS94 word set for files, and I didn't see file handling mentioned at all in the older standards. I'm going to be generally assuming that my hardware is working and not check for or report any errors (eg. the "ior" or I/O Result Code will always be 0 meaning nothing went wrong). I'm also trying just to get reading of files to work before I even think about how to write to them.
I had some issues writing some of these words (especially with doubles and single cells mixed on the stack), so I still have stack comments left in them. That was quite handy for debugging them, but I did have the lingering thought that I should make a new word for stack comments, perhaps "SC(" for Stack Comments, that prints out what I think should be on the stack and the actual values that are there - I could even make it a deferred word so that I could change it to just be silent when I'm not debugging anymore. Forth is a bit mind bending when you realize that you can make it do whatever you want that seems useful or amusing.
I didn't end up writing my stack comment helper word, but I'd be interested in how others do debugging. I found the ability to copy and paste chunks of code and then be able to inspect the stack very helpful, along with dump for checking my buffers and data structures. I also snuck a bunch of ".s" in the tricky spots.
Once I got that working, it was time make some useful words:
And finally running it:
It works! The LCD.FS file is 668 bytes, so it crosses over a sector change in the middle. I have another file that is 15K, and my fat32 partition has 4K clusters (8 sectors per cluster) so I've tested the cluster to cluster hopping using the FAT as well.
I had some issues writing some of these words (especially with doubles and single cells mixed on the stack), so I still have stack comments left in them. That was quite handy for debugging them, but I did have the lingering thought that I should make a new word for stack comments, perhaps "SC(" for Stack Comments, that prints out what I think should be on the stack and the actual values that are there - I could even make it a deferred word so that I could change it to just be silent when I'm not debugging anymore. Forth is a bit mind bending when you realize that you can make it do whatever you want that seems useful or amusing.
I didn't end up writing my stack comment helper word, but I'd be interested in how others do debugging. I found the ability to copy and paste chunks of code and then be able to inspect the stack very helpful, along with dump for checking my buffers and data structures. I also snuck a bunch of ".s" in the tricky spots.
Code: Select all
\ Continued from previous code
: bin ; ( Required by ANS, but we're ignoring it. )
( File access methods )
1 constant r/o 2 constant w/o 3 constant r/w
: findfile ( fileid 'findfile direntry_addr -- f )
( This word is used to help find a file in a directory )
( with walkdirectory. It needs the address of a fileid )
( structure with just the name filled in to be on the )
( stack -- under the things walkdirectory needs. )
( cr ." checking " dup 0B type cr .s ( DEBUG )
0B ( length to compare )
3 pick ( bring fileid struct address over )
( >filename -- but offset is zero)
0B compare ;
: eof? ( fileid -- f ) ( return true if at end of file )
dup >fileposition 2@ rot >filesize 2@ d= ;
( open-file - simplified for read-only access )
: open-file ( c-addr u fam -- fileid ior )
>r ( save fam )
newfileid ( Allot memory for the file info )
( c-addr u fileid ) -rot 2 pick swap move ( filename )
( fileid ) r> over >attrib c! ( save fam )
( fileid ) working_dir init_directory
( fileid ) ['] findfile working_dir walkdirectory
( fileid direntry|0 )
?dup 0= if
cr ." Can't open file: " dup 0B type cr
1 ( ior of 1 = Can't open file ) exit
then
( fileid direntry ) swap >r ( save fileid )
dup >clustLOW @ ( first cluster LSB )
over >clustHI @ ( first cluster MSB )
( direntry firstcluster.d )
2dup r@ >firstcluster 2! ( Save first cluster )
2dup r@ >currentcluster 2! ( start at first cluster )
( direntry firstcluster.d )
cluster>sector r@ >currentsector 2! ( starting sector )
( direntry ) dup >filesize 32bit@ r@ >filesize 2!
( direntry ) drop ( Done with direntry )
r> ( bring back fileid structure )
dup >fileposition d0!
dup >linestart d0!
0 ( no errors/exceptions )
;
: read-char ( fileid -- c ) ( Note: does not check eof )
dup >currentsector 2@ sector>buffer ( Get the sector )
dup >fileposition 2@ ( Get the position in the file )
drop 200 ( 512 ) mod ( Get offset into buffer )
sectorbuff + c@ swap ( Get the character )
( c fileid )
( Move to next character )
dup >fileposition d1+! ( increment fileposition )
( Check to see if we've wrapped to a new sector )
dup >fileposition 2@ drop 200 ( 512 ) mod 0= if
nextsector ( uses fileid ) else drop ( the fileid )
then
;
: file-position ( fileid -- ud ior )
>fileposition 2@ ( Get current position )
0 ( No error ) ;
: file-size ( fileid -- ud ior )
>filesize 2@ ( Get file size )
0 ( No error ) ;
: sectorff ( #bytes.d fileid -- )
( Sector fast-forward - follow FAT chain )
( to determine current cluster/sector values. )
( Assumes starting from beginning of file. )
>r ( Save fileid )
( Move to next sector for every 512 bytes )
( Divide count by 512 - using shifts )
9 drshift
begin
2dup d0<>
while
r@ nextsector ( Move to the next sector )
1. d- ( Reduce the count )
repeat
r> drop 2drop ;
: reposition-file ( ud fileid -- ior )
>r ( Save the fileid )
r@ >filesize 2@ 2over ( newpos filesize newpos )
d< if ( Check bounds )
." Cannot resize beyond end of file"
r> drop 2drop exit then
( New position is ok. Save it. )
2dup r@ >fileposition 2!
( Rewind the file to the first sector )
r@ >firstcluster 2@ ( Get the first cluster )
2dup r@ >currentcluster 2! ( Make first cluster current )
cluster>sector ( Determine sector for this cluster )
r@ >currentsector 2! ( Make that the current )
r> sectorff ( Follow the FAT chains to the right sector )
0 ( IO Result - no error ) ;Code: Select all
\ Continued from previous code
: catfile ( fileid -- ) ( Copy file contents to screen )
>r ( Save fileid ) cr ( Start on the next line )
begin r@ eof? 0= while r@ read-char emit repeat r> drop ;
: rewind ( fileid -- )
( Move fileposition back to beginning of file )
0. rot reposition-file drop ;Code: Select all
: lcd.fs s" LCD FS " ; ( A filename in direntry format ) ok
lcd.fs r/o open-file drop constant lcdfileid ok
lcdfileid catfile
( LCD Routines - SamCo - 2018-11-15 ) hex
: lcd-init ( -- ) 38 7FC0 c! 0E 7FC0 c! ;
: lcd-busy ( -- ) ( Wait until LCD is not busy )
begin 7FC0 c@ 80 and while repeat ;
: lcd-cmd ( cmd -- ) ( Send an LCD command )
lcd-busy 7FC0 c! ; allow-native
: lcd-char ( char -- ) ( Send an LCD character )
lcd-busy 7FC1 c! ; allow-native
: lcd-type ( addr n -- ) ( Send a string to the LCD )
0 ?do dup i + c@ lcd-char loop drop ;
: lcd." ( Make and send string ) postpone s" lcd-type ;
( Helper words )
: lcd-line1 ( -- ) 80 lcd-cmd ; allow-native
: lcd-line2 ( -- ) C0 lcd-cmd ; allow-native
: lcd-clear ( -- ) 01 lcd-cmd ; allow-native
decimal
ok