Jump to content
IGNORED

fbForth—TI Forth with File-based Block I/O [Post #1 UPDATED: 06/09/2023]


Lee Stewart

Recommended Posts

53 minutes ago, TheBF said:

I can understand @HOME AUTOMATION 's   confusion emoji. 

This is outside the realm of normal Forth application programming.

We are modifying how the compiler works, which is fair game in Forth but it means you must have "carnel knowledge"  of the system.

Haha... The post was blank/empty when I reacted... I don't yet understand fourth well enough to know what is within the realm of normality!

 

   P.S. Shouldn't that be "caramel knowledge"!:-D

  • Like 1
  • Haha 2
Link to comment
Share on other sites

1 hour ago, HOME AUTOMATION said:

Haha... The post was blank/empty when I reacted... I don't yet understand fourth well enough to know what is within the realm of normality!

 

   P.S. Shouldn't that be "caramel knowledge"!:-D

Forth is kind of like smoking. 

It's never too late to start! :lolblue:

  • Thanks 1
Link to comment
Share on other sites

2 hours ago, HOME AUTOMATION said:

The post was blank/empty when I reacted...

 

You were too quick! I was trying to figure out how to quote another thread and was not getting very far. I, finally, just copied and pasted its contents and used ( ) from the menu bar—close enough.

 

...lee

  • Like 1
Link to comment
Share on other sites

On 12/16/2021 at 7:07 PM, TheBF said:

Right and that is faster that my method.

I was referring to how one might make DATA xxxx,xxxx,  word in Fig-Forth.

Something like: 


: DATA ( -- )
         BEGIN
            ASCII , WORD  
            HERE C@
         WHILE
            HERE INTERPRET ,
         REPEAT
         DROP DROP ;

Would that work?

 

The problem with INTERPRET in figForth is that it does not take an address. Rather, it uses the user variables, BLK and IN , for the next token ( IN ) of the input stream ( BLK ). If BLK contains 0, the input stream is the Terminal Input Buffer ( TIB ), otherwise, the input stream is the block number contained in BLK .

 

We could use NUMBER as below,

: DATA ( -- )  \ Compile string of 16-bit integers
   BEGIN
      ASCII , WORD      \ get next comma-delimited token to HERE
      HERE C@           \ token-length to stack
   WHILE
      HERE NUMBER          \ convert token at HERE to a double on stack
      ABORT" > 16 bits!"   \ top of stack should be 0
      ,                    \ compile the 16-bit integer
   REPEAT   ;

except that the token after the end of the DATA string is not zero-length. And, it looks as though different things are happening depending on the input stream. We may need to use a terminator, but I am going to investigate what happens for TIB and block interpretation before I go that route.

 

...lee

  • Like 1
Link to comment
Share on other sites

So perhaps you Rstack BLK and IN 

Then set BLK to HERE and reset IN to zero

Do interpret and then restore BLK and IN when you are finished?

 

I remember that I never fully understood how that all hooked together when I was using TI-FORTH. :)

 

 

 

 

 

 

 

Link to comment
Share on other sites

1 hour ago, TheBF said:

So perhaps you Rstack BLK and IN 

Then set BLK to HERE and reset IN to zero

Do interpret and then restore BLK and IN when you are finished?

 

I remember that I never fully understood how that all hooked together when I was using TI-FORTH. :)

 

BLK does not contain an address. It contains a block number—0 for TIB and other integers for blocks 1 – n. It is actually WORD (called by INTERPRET ) that uses BLK and IN to find the next token in the input stream.

 

...lee

  • Like 3
Link to comment
Share on other sites

OK—The following code works as a port of @TheBF’s CAMEL99 Forth BYTE and DATA words for compiling bytes and words into the fbForth 2.0 dictionary:

\ DATA and BYTE directive with comma delimiting
\ More compatible with TI ASM DATA statements Jan 2018
\ Ported to fbForth 2.0 01JAN2022 LES

\ Usage:
\ HEX
\ DATA DEAD,BEEF,AABB
\ DATA 0001,2200,3300,4440
\ BYTE 00,01,02,03,FF,BEEF  (aborts on 'BEEF')

HEX
: BYTE,  ( n addr -- addr )    
   \ n = byte to compile
   \ addr = address of next number to process
   OVER FF00 AND ABORT" Not a byte!"    \ is it a byte?                 
   SWAP C,  ;        \ compile the byte to HERE                         

: CELL,  ( n addr -- addr )
   \ n = cell to compile
   \ addr = address of next number to process
   SWAP ,   ;        \ compile the word to HERE                         

: B|W,   ( n addr -- addr )   \ compile a byte or a word
   \ n = byte|cell to compile
   \ addr = address of next number to process
   BYTE,   ;         \ placeholder for BYTE, or CELL,

: B|W  ( -- )  ( IS:string )  \ Compile string of bytes|words
   BL TOKEN             \ comma-separated byte-string to PAD..leave address
   DUP C@ OVER + >R     \ address of end of string to return stack   
   BL R 1+ C!           \ <space> after string                             
   BEGIN       \ still have address of string
      0 0 ROT (NUMBER)           \ double and end address to stack         
      SWAP ABORT" > 16 bits!"    \ MSW should be 0                         
      B|W,              \ compile byte|cell
      DUP R >           \ address of next number                           
   UNTIL                                                                   
   DROP R> DROP   ;     \ clean up

: BYTE ( -- )  ( IS:string )  \ Compile string of bytes
   ' BYTE, CFA ' B|W, !    \ store CFA of BYTE, in B|W,
   B|W   ;        \ convert and compile string of bytes to HERE

: DATA ( -- )  ( IS:string )  \ Compile string of 16-bit integers
   ALIGN          \ insure HERE is at an even address
   ' CELL, CFA ' B|W, !    \ store CFA of CELL, in B|W,   
   B|W   ;        \ convert and compile string of cells to HERE

Perhaps a bit convoluted, but it works. I might rework the code and maybe we can come up with some cleverer word names. |:)

 

...lee

Edited by Lee Stewart
CORRECTION of some stack effects
  • Like 2
Link to comment
Share on other sites

1 minute ago, TheBF said:

Interesting. You are doing some serious vectoring with B|W,

Is TOKEN a word you made for this or did you have it before. 

 

I wrote TOKEN into the kernel years ago to help me with words like MKBFL , USEBFL , S" , ."  , WLITERAL and USEFFL . When interpreting, it puts the string at PAD and leaves the address on the stack. When compiling, it puts the string at HERE and must be handled with SLIT to keep track of it within the compiled word.

 

...lee

  • Like 2
Link to comment
Share on other sites

In Starting Forth there was a word called TEXT...  gotta get the book ...

that did something similar although it was not used in compiling.

It is defined as:

: TEXT     PAD 72 32 FILL    WORD  COUNT PAD SWAP <CMOVE ; 

But like the old version of WORD it doesn't return the address where the data is. :(

The ANS gang factored out a lot of interpreter to make it more accessible.

It still gives me grief but as you show with TOKEN you just make what you need. 

It's mostly fun. I am trying to find a bug in my cross-compiler which is not fun right now.

  • Like 1
Link to comment
Share on other sites

22 minutes ago, TheBF said:

In Starting Forth there was a word called TEXT ...  gotta get the book ...

that did something similar although it was not used in compiling.

It is defined as:


: TEXT     PAD 72 32 FILL    WORD  COUNT PAD SWAP <CMOVE ; 

But like the old version of WORD it doesn't return the address where the data is. :(

The ANS gang factored out a lot of interpreter to make it more accessible.

It still gives me grief but as you show with TOKEN you just make what you need. 

It's mostly fun. I am trying to find a bug in my cross-compiler which is not fun right now.

 

In the old version of WORD , the address was known to be at HERE . Of course, you had to use it before HERE was corrupted. Here are the Starting Forth compatibility comments from the TI Forth manual, adapted to fbForth 2.0:

 

image.png.3f994176ec0c1f8758d53a20af4c9e88.png

 

The above assumes the address of PAD , which, as with WORD , must be used before it changes.

 

FYI, TOKEN , uses  WORD with the same trick the TI programmers used in TXT above, viz., ALLOTing space to move HERE to PAD and, then restoring HERE by ALLOTing that same amount as a negative number—no need to copy the string somewhere else. For the hosts of the curious, TOKEN is shown in the spoiler:

 

Spoiler

\ TOKEN gets a string ending with delim from the input stream into
\ PAD as a packed string and passes address of string's count byte
\ on the stack if interpreting [command line], but compiles the
\ packed string to HERE, with nothing to the stack, if compiling.
: TOKEN  ( delim --- [addr] | [] )   ( IS:string )
   STATE @
   IF          \ compiling
      WORD           \ get string to HERE
      HERE C@ 1+     \ compute length of string
      =CELLS ALLOT   \ move HERE by that much effectively compiling string
   ELSE        \ interpreting
      PAD HERE -     \ compute distance to PAD
      DUP ALLOT      \ DUP it and move HERE to old PAD
      MINUS          \ negate ALLOTment for later restore
      SWAP           \ get delimiter to top of stack
      WORD           \ get string to new HERE (old PAD)
      ALLOT          \ restore old HERE (and old PAD)
      PAD            \ return address of string on stack
   THEN    ;

 

 

...lee

  • Like 2
  • Thanks 1
Link to comment
Share on other sites

1 hour ago, Lee Stewart said:

 

In the old version of WORD , the address was known to be at HERE . Of course, you had to use it before HERE was corrupted. Here are the Starting Forth compatibility comments from the TI Forth manual, adapted to fbForth 2.0:

 

image.png.3f994176ec0c1f8758d53a20af4c9e88.png

 

The above assumes the address of PAD , which, as with WORD , must be used before it changes.

 

FYI, TOKEN , uses  WORD with the same trick the TI programmers used in TXT above, viz., ALLOTing space to move HERE to PAD and, then restoring HERE by ALLOTing that same amount as a negative number—no need to copy the string somewhere else. For the hosts of the curious, TOKEN is shown in the spoiler:

 

  Reveal hidden contents


\ TOKEN gets a string ending with delim from the input stream into
\ PAD as a packed string and passes address of string's count byte
\ on the stack if interpreting [command line], but compiles the
\ packed string to HERE, with nothing to the stack, if compiling.
: TOKEN  ( delim --- [addr] | [] )   ( IS:string )
   STATE @
   IF          \ compiling
      WORD           \ get string to HERE
      HERE C@ 1+     \ compute length of string
      =CELLS ALLOT   \ move HERE by that much effectively compiling string
   ELSE        \ interpreting
      PAD HERE -     \ compute distance to PAD
      DUP ALLOT      \ DUP it and move HERE to old PAD
      MINUS          \ negate ALLOTment for later restore
      SWAP           \ get delimiter to top of stack
      WORD           \ get string to new HERE (old PAD)
      ALLOT          \ restore old HERE (and old PAD)
      PAD            \ return address of string on stack
   THEN    ;

 

 

...lee

Lee what address was pad and how much space is there- and can it be forgotten and moved to SAMs?

Link to comment
Share on other sites

5 minutes ago, GDMike said:

Lee what address was pad and how much space is there- and can it be forgotten and moved to SAMs?

 

PAD is always a fixed distance above HERE (68 bytes in TI Forth and fbForth). Every time HERE changes, so does PAD . It is a temporary workspace and, obviously, cannot be depended on to be constant.

 

...lee

Edited by Lee Stewart
CLARIFICATION
  • Like 2
  • Thanks 1
Link to comment
Share on other sites

14 minutes ago, Lee Stewart said:

PAD is always a fixed distance above HERE (68 bytes in TI Forth and fbForth). Every time HERE changes, so does PAD . It is a temporary workspace and, obviously, cannot be depended on to be constant.

 

...lee

 

PAD is termed the “text output buffer”. I am really not sure of the reason for PAD being a 68-byte offset above HERE . I may change this to give more space in the next build of fbForth 2.0, but I can think of only one significant use of the in-between space and that is the formatting of numbers with <# ... #> . The ASCII representation of the number grows down from PAD toward HERE because the formatting is done from right to left and the offset space must accommodate the text for a double number. The other significant use of PAD (before my kernel definition of TOKEN ) is by the block editors, which manage copying and pasting of lines of 64 bytes to and from PAD , but they grow toward high memory and do not really impact the in-between space. FWIW TurboForth reserves a space of 80 bytes between HERE and PAD . Maybe I should go with that in the next build.

 

...lee

  • Like 2
Link to comment
Share on other sites

13 hours ago, Lee Stewart said:

PAD is always a fixed distance above HERE (68 bytes in TI Forth and fbForth). Every time HERE changes, so does PAD . It is a temporary workspace and, obviously, cannot be depended on to be constant.

 

...lee

 

To insure that this dead horse is well and truly expired, the reason that PAD (in TI Forth and fbForth) always changes with HERE is that its very definition is so based:

: PAD   ( --- addr )
   HERE 68 +  ;

I should probably add here that Mark Wills (@Willsy) wrote PAD for TurboForth to not only place it 80 bytes above HERE (usually) but also to attempt to insure there is a space of at least 84 bytes above PAD for the “text output buffer”. For the terminally curious, Mark’s Assembler code for PAD is in the spoiler below. You will learn more from his comments rather than trying to parse his ALC:

Spoiler

;[ PAD         ( -- addr )                      83                   
; The lower address of a scratch area used to hold data for
; intermediate processing.
; The address or contents of PAD may change and the data lost
; if the address of the next available dictionary location is
; changed. The minimum capacity of PAD is 84 characters.
PADH    DATA FFALH,3
        TEXT 'PAD '
PAD     DATA $+2
        MOV @FFAIHM,R6     ; get first free address in HIGH memory
        CI R6,>FFA8        ; compare to end of low memory-86 bytes
        JLT PADX           ; if less than then ok, just exit
        ; otherwise, we're close to the end of high memory, so...
        MOV @FFAILM,R6     ; offer an address in low memory
PADX    AI R6,80           ; add a margin
        JMP DOVAR
;]

 

 

...lee

  • Like 4
Link to comment
Share on other sites

I think that horse still has weak pulse. :) 

 

Something to watch out for when you run the FbForth multi-tasker.

 

PAD becomes a shared resource.  I have the  "68" value in your FbForth kept in a user variable called TPAD (task pad)

: PAD      HERE TPAD @ + ;  

If a task needs it's own PAD you set its local TPAD variable to a higher value when the task starts or manually in the program's startup code. 

You need enough space for the task's PAD and it's HOLD buffer as well. 

 

  • Like 2
Link to comment
Share on other sites

33 minutes ago, Lee Stewart said:

 

To insure that this dead horse is well and truly expired, the reason that PAD (in TI Forth and fbForth) always changes with HERE is that its very definition is so based:


: PAD   ( --- addr )
   HERE 68 +  ;

I should probably add here that Mark Wills (@Willsy) wrote PAD for TurboForth to not only place it 80 bytes above HERE (usually) but also to attempt to insure there is a space of at least 84 bytes above PAD for the “text output buffer”. For the terminally curious, Mark’s Assembler code for PAD is in the spoiler below. You will learn more from his comments rather than trying to parse his ALC

...lee

Ooh yes - I remember that. IIRC TF cheats and uses HERE+0 as the screen scroll buffer (hence the requirement for 80 plus a bit characters). It might be that it uses HERE as the TIB. My memory is fading!

 

Just checked - the screen up-scroll routine (when the cursor is at the bottom of the screen) uses HERE as a buffer. The old grey matter isn't as bad as I thought it was :rolling:

(http://turboforth.net/source/Bank0/0-09-Console.html)

; Scroll screen up by one line. Used by EMIT and CR to scroll the screen up if
; necessary (sub-routine, not a FORTH word).
scrlup  mov @noscrl,r8              ; test NOSCROLL
        jeq scrlno                  ; scrolling is supressed
        dec @scrY                   ; clip y coordinate to 23
        mov @here,r8 <--- dun dun duuuuh!
        ai r8,4
        li r6,23                    ; 23 lines to shift
        clr r0                      ; screen address
sclup_  a @xmax,r0                  ; move down one line
        mov r8,r1                   ; address of buffer to store in
        mov @xmax,r2                ; number of bytes to store in the screen

I've been checking the site a lot these last three days - looking at old Forth threads and catching up on fbForth and Forth99 developments. This is bad news as I'll probably get dragged into something I don't have the time for ;)

Happy new year Lee! :waving:

  • Like 5
Link to comment
Share on other sites

  • 1 month later...

Among the changes for fbForth 2.0:14 (maybe it’s time to make this fbForth 3.0?) I am working on is the Floating Point Library (FPL). The FPL currently resides in the fbForth 2.0 ROM, so is bound to 8-bit instruction processing. What I am changing is all of the FPL that can use the corresponding routines in console ROM because they are on the 16-bit bus. The E/A Manual references for these routines, which are available through XMLLNK, are FADD,FSUB,FMUL,FDIV,FCOM. I would like to use the addresses of these routines directly, without calculating them every time they are required as the XMLLNK word does. This would require that their addresses never change across the handful (2?) of console versions of the TI-99/4A out there. I can manage the address calculations at startup if necessary, but I would rather not. Does anyone know whether these addresses are , indeed, constant?

 

...lee

  • Like 1
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...