6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Tue Jun 04, 2024 6:02 am

All times are UTC




Post new topic Reply to topic  [ 343 posts ]  Go to page Previous  1 ... 19, 20, 21, 22, 23
Author Message
PostPosted: Thu Apr 18, 2024 11:49 pm 
Offline

Joined: Fri May 05, 2017 9:27 pm
Posts: 864
JimBoyd wrote:

Here is DOWN-COUNTER for Fleet Forth.
Code:
: DOWN-COUNTER
   2VARIABLE  ( -- )
   DOES>  ( -- ADR )
      JIFFY@ DROP
      OVER 2+ @
      OVER -  0 MIN
      2PICK +!
      OVER 2+ ! ;

That '0 MIN' is to handle the case when the jiffy timer resets to zero when it reaches twenty four hours.
A down-counter, a child word of DOWN-COUNTER , has two cells of storage. The first cell holds a value. The second cell holds the low cell of the Commodore 64 jiffy clock from the last time the down-counter was executed. Each time a down-counter is executed the amount of time, in jiffies, which passed from the last time is subtracted from the value in the first cell.
Code:
DOWN-COUNTER DELAY1 OK
300 DELAY1 ! OK
DELAY1 ? 209  OK
DELAY1 ? 118  OK
DELAY1 ? 5  OK
DELAY1 ? -445  OK

Of course, the values returned each time I type "DELAY1 ?" depends on how long I wait.

Here is a slightly improved version of DOWN-COUNTER .
Code:
: DOWN-COUNTER
   2VARIABLE  ( ++ )
   DOES>  ( -- ADR )
      JIFFY@ DROP           \ Only need low cell of jiffy clock
      OVER 2@ SWAP 2PICK -  \ new.time value -delta.time
      0 MIN                 \ Compensate for reset at midnight.
      +  2PICK 2! ;         \ add negative time difference to
                            \ old value and store new time
                            \ and new value to down-counter
                            \ variable and leave address.

JIFFY@ leaves the value of the Commodore 64 jiffy clock on the stack as a double number. Yes the jiffy clock resets to zero after twenty four hours.
2PICK is syntactically equivalent to 2 PICK .
Code:
CODE 2PICK  ( N1 N2 N3 -- N1 N2 N3 N1 )
   4 ,X LDA  5 ,X LDY
   AYPUSH JMP  END-CODE

A DOWN-COUNTER is used when some code is run periodically, but there is a portion which must be run less often.
Code:
DOWN-COUNTER DELAY

     .
     .
     .
   DOWN-COUNTER @ 0<          \
   IF                         \ If this code fragment is run often enough
      #3600 DOWN-COUNTER !    \ <DO.SOMETHING> only runs
      <DO.SOMETHING>          \ once a minute.
   THEN                       \
     .
     .
     .



Top
 Profile  
Reply with quote  
PostPosted: Tue Apr 23, 2024 10:37 pm 
Offline

Joined: Fri May 05, 2017 9:27 pm
Posts: 864

Fleet Forth is not a multi user Forth system. It was designed for one person to use at a time on a Commodore 64. Fleet Forth supports multitasking with background tasks. With this in mind the Fleet Forth system has only ten user variables. More user variables can be added.
The user area for the foreground task is not part of the loadable image, it is in a section of unused memory on the Commodore 64; therefore, the first eight user variables need initialized at bootup. Fleet Forth's boot area holds the bootup values for the first seven user variables.
Code:
ENTRY  -- Points to next task's user area or itself if no other tasks.
READY  -- Flag. TRUE - task is awake. FALSE - task is asleep.
TOS    -- Holds the return stack pointer when a task is switched out.
RP0    -- Base of return stack.
SP0    -- Base of data stack.
AP0    -- Base of auxiliary stack.
DP     -- Dictionary Pointer.

The first six user variables are initialized by the word UNLINK , which also sets the user pointer UP to the address of the foreground task's user area. This unlinks all background tasks and restores control to the main task. UNLINK is included in a routine included in the coldstart and warmstart routines.
The word EMPTY initializes DP from this bootup area and branches into the body of FORGET to handle any necessary pruning. EMPTY is included in the coldstart routine.
These are the next three user variables:
Code:
BASE   -- Base for numeric conversion to or from text.
DPL    -- Decimal place.
HLD    -- Holds the address for the next character during conversion
          from text to a double number.

DECIMAL , which sets BASE to decimal, is included in the routine which is included in the coldstart and warmstart routines.

DPL and HLD are not initialized during coldstart or warmstart. It is not required. NUMBER? initializes DPL and <# initializes HLD .
The Fleet Forth system has only ten user variables. The other variables in the system are not user variables as they should not be needed in background tasks.

As I mentioned, Fleet Forth allows the defining of new user variables. The word for this is USER . It takes a number and is followed by a name.
Code:
<USER.AREA.OFFSET> USER <NAME.OF.USER.VARIABLE>

For example:
Code:
#20 USER STOOGES

To make defining new user variables easier (some may be defined in different sources), Fleet Forth has a 'system value' or 'soft constant' #USER .
The source for Fleet Forth's USER .
Code:
: USER  ( N -- )
   DUP 2+ #USER UMAX (IS) #USER
   CREATE C,
   ;CODE  ( -- N )
      2 # LDY  CLC
      W )Y LDA  UP ADC
      UP 1+ LDY  CS IF  INY  THEN
      AYPUSH JMP  END-CODE

If #USER has the value #20, the following:
Code:
#USER USER LARRY
#USER USER CURLY
#USER USER MOE

will create the user variable LARRY with the user area offset #20, the user variable CURLY with the user area offset #22, and the user variable MOE with the user area offset #24.
To set aside more of the user area for a particular user variable, the following can be done.
Code:
#USER USER LAUREL
#USER 8 + USER HARDY

This will 'allot' eight more bytes in the user area for the user variable LAUREL .


Top
 Profile  
Reply with quote  
PostPosted: Sun Apr 28, 2024 9:39 pm 
Offline

Joined: Fri May 05, 2017 9:27 pm
Posts: 864
JimBoyd wrote:
I've just streamlined DJIFFIES , the word that takes a positive double number and waits that many jiffies ( 1/60th of a second on the Commodore 64 ) . It is also used by JIFFIES , the word that takes an unsigned single number and waits that many jiffies.
DJIFFIES works by keeping the number of jiffies to delay on the stack as well as the latest jiffy clock value. Each time through the loop, it subtracts the difference from the amount of time to wait. The idea came from DOWN-COUNTER on page 130 ( 140 of the PDF ) in the book Real Time Forth by Tim Hendtlass.
When I was testing my multitasker, I noticed that the loop in DJIFFIES runs several times per jiffy. With three background tasks, two using DJIFFIES ( actually JIFFIES ) for a delay and one counting how many times it runs, the entire round robin runs several times a jiffy. I realized that when the difference between the current jiffy clock value and the previous one is subtracted from the amount of time to delay, either 0 or -1 is added to the remaining time. I only needed to use the lower cell of the jiffy clock value. Here is the code:
Code:
SCR# 41
// DJIFFIES
HEX
// TAKES POSITIVE DOUBLE NUMBER
// AND DELAYS THAT MANY JIFFIES
: DJIFFIES  ( D+ -- )
   JIFFY@ DROP
   BEGIN
      PAUSE
      JIFFY@ DROP  DUP>R -
// COMPENSATE FOR RESET AT 24 HOURS
      0 MIN
      S>D D+  R> OVER 0<
   UNTIL
   DROP 2DROP ;

SCR# 42
// JIFFIES
HEX
: JIFFIES  ( U -- )
   0 DJIFFIES ;

JIFFIES takes an unsigned number and has a maximum delay of:
18 minutes 12 seconds and 15 jiffies.
DJIFFIES takes a positive double number and has a maximum delay of:
414 days 6 hours 3 minutes 14 seconds and 7 jiffies or
2,147,483,647 jiffies.


Because DJIFFIES waits until the count goes negative, DJIFFIES and JIFFIES wait one jiffy more than what is requested. Not a big problem. There is an easy solution. Just subtract one from the initial value returned by JIFFY@ DROP .
Code:
// DJIFFIES JIFFIES
// TAKES POSITIVE DOUBLE NUMBER
// AND DELAYS THAT MANY JIFFIES
: DJIFFIES  ( D+ -- )
   JIFFY@ DROP 1-
   BEGIN
      PAUSE
      JIFFY@ DROP  DUP>R -
      // COMPENSATE FOR DAILY RESET
      0 MIN
      S>D D+  R> OVER 0<
   UNTIL
   DROP 2DROP ;
: JIFFIES  ( U -- )
   0 DJIFFIES ;

Now DJIFFIES and JIFFIES will wait the requested number of jiffies.
Note: // (double forward slash) is a Commodore 64 Forth alias for \ (backslash) .


Top
 Profile  
Reply with quote  
PostPosted: Sun Apr 28, 2024 10:16 pm 
Offline

Joined: Fri May 05, 2017 9:27 pm
Posts: 864

In a previous post I showed the source for Fleet Forth's word USER , the word to create new user variables. I also mentioned #USER. The only user variables I've ever defined other than the ones defined in the kernel are the three user variables used for multitasking. They have the offsets 0, 2, and 4.
Code:
0 USER ENTRY   2 USER READY
4 USER TOS

Other than these three, I have never defined new user variables; therefore, I simplified the source for USER and removed #USER from Fleet Forth's kernel.
Code:
: USER  ( N ++ )
   CREATE
      C,
   ;CODE  ( -- ADR )
      2 # LDY  CLC
      W )Y LDA  UP ADC
      UP 1+ LDY  CS IF  INY  THEN
      AYPUSH JMP  END-CODE

I also had to change the source for the multitasker's task creation word TASK .
Code:
// TASK CREATION AND ACTIVATION
: TASK  ( U AP0 SP0 RP0 -- )
   CREATE
        ( -- TADR )
      HERE RP0 LOCAL !
      HERE SP0 LOCAL !
      HERE AP0 LOCAL !
      [ ' STOP >BODY ] LITERAL
      HERE ACTIVATE
      // OPTIONAL
      #10 HERE BASE LOCAL !
      [ 0 HLD LOCAL 2+ ] LITERAL
      HERE +  HERE DP LOCAL !
      #12 UMAX ALLOT ;

Note that HLD is the last user variable defined in the kernel. It has an offset of eighteen. The line
Code:
      [ 0 HLD LOCAL 2+ ] LITERAL

compiles a literal decimal twenty. Since there are a total of ten user variables, this points the task's DP just past the area used by the last user variable. Setting a task's DP to point twenty bytes into a task's user area is done so data stored at a background task's HERE will not overwrite any of the task's user variables.


Top
 Profile  
Reply with quote  
PostPosted: Thu May 02, 2024 10:19 pm 
Offline

Joined: Fri May 05, 2017 9:27 pm
Posts: 864
JimBoyd wrote:

Here is my find and replace function.
Code:
: FR
   BEGIN F R AGAIN ; -2 ALLOT


There was one flaw in the editor word FR . As I mentioned, FR can be used to find all occurrences of a given string in a screen and replace them.
Code:
FR HEX^DECIMAL

and used in another screen without specifying the strings to perform the same search and replace.
Code:
FR

When the editor word F searches for a string, it first parses the text stream for a search string delimited by the caret character to place in the find buffer. If the text stream is exhausted, the old search string remains in the find buffer. Whatever string is in the find buffer is used for the search. Likewise, the editor word I , which is used by R , parses the text stream for a string to insert and places this string in the insert buffer.
If the search string was not found when FR was used with the search and replacement strings specified, the replacement string was never placed in the insert buffer. When FR was then used without specifying the search and replace strings, the string to be found would be replaced with garbage (whatever was in the insert buffer).
The following improvement to FR places the search string in the find buffer and the replacement string in the insert buffer before the first search attempt.
Code:
: FR
   >FBUF  >IBUF
   BEGIN  F R  AGAIN -;

>FBUF and >IBUF are the words which parse the text stream and place a string in the find buffer and insert buffer respectively.
With this modification, I no longer have a problem with FR .

Quote:

Unlike S , F ( find) and R ( replace) are limited to one screen at a time. If F can't find the string it aborts. I'm changing that to QUIT so it will not clear the data and auxiliary stacks.

I made that change.


Top
 Profile  
Reply with quote  
PostPosted: Thu May 16, 2024 12:07 am 
Offline

Joined: Fri May 05, 2017 9:27 pm
Posts: 864

Fleet Forth is an ITC Forth for the Commodore 64 and has to compensate for the indirect jump bug; therefore, when I mentioned defining multi code field words with Fleet Forth, I mentioned a word named CFA-ALIGN to make sure the other CFA's of a multi code field word don't straddle a page boundary by forcing an even address alignment for these CFA's by adding a pad byte before the header is created. The need to define CFA-ALIGN whenever I wished to experiment with adding an extra Code field or two contributed to my reluctance to add extra code fields.
This will no longer be a problem. Fleet Forth's CREATE would compute the address of the yet to be created word's code field. If the code field would start on an address ending in $FF, it would allot a byte before creating the header. This test in CREATE has been modified so that if the CFA would start on an address ending in $FF, $FD, $FB, $F9 or $F7 CREATE will allot a byte before the header is created.
Removing the out of memory check from the code below for clarity, the old test was something like this:
Compute the address of the code field.
Code:
   HERE COUNT + 2+  VIEW @ TUCK
   IF  2+  THEN

and allot one byte if it ends with $FF.
Code:
   1+ SPLIT DROP
   0= ABS ALLOT


The code to compute the address of the code field is unchanged.
Code:
   HERE COUNT + 2+  VIEW @ TUCK
   IF  2+  THEN

but the test is now this.
Code:
   DUP 9 + SPLIT DROP
   9 U< AND  2 MOD ALLOT

This change only added twelve bytes to CREATE . Fleet Forth can now support words with up to five code fields without the need to perform any address check other than what CREATE now does.

I think three code fields are typical with multi code field words. Supporting five gives a little extra just in case.

There is one other case where the improved CREATE is helpful. When modifying Blazin' Forth's utilities for Fleet Forth, it was necessary to test the body of the variable SYSIRQ for page crossing.
Code:
HEX
// BUG FIX
" SYSIRQ" C@ HERE + 1+
2+ 2+         // SIZE OF LINK
              // & CODE FIELDS
SPLIT DROP 0FF = // WILL PFA BE ON
              // PAGE BOUNDARY?
ABS ALLOT     // IF SO BUMP IT PAST
VARIABLE SYSIRQ

The variable SYSIRQ is used to hold the address of the last part of the Commodore 64's interrupt service routine which is vectored through address $314. Blazin' Forth's interrupt service routine jumps to the Commodore 64's routine by indirectly jumping through the parameter field of the variable SYSIRQ . If this address straddles a page boundary, the indirect jump bug strikes.
With Fleet Forth's new CREATE , the test before defining SYSIRQ is no longer needed.


Top
 Profile  
Reply with quote  
PostPosted: Thu May 16, 2024 12:33 am 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8453
Location: Southern California
I lay the name field down first, and then do ALIGN which makes sure the LFA, CFA, and PFA are aligned.  It probably makes L>NAME a little more complex, but I allow characters above $7F anyway for the special characters in the DOS/ANSI (code page 437) characters, and it makes CREATE a little simpler.

_________________
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?


Top
 Profile  
Reply with quote  
PostPosted: Thu May 16, 2024 12:47 am 
Offline

Joined: Fri May 05, 2017 9:27 pm
Posts: 864

If roughly half the words would have a code field on an odd address then those half would need an extra byte. On a system with lots of words, that's a lot of bytes.
The fields of a word in Fleet Forth are in the following order: Link field, Name field, Code field and Parameter Field. A word's link field points to the previous word's link field.


Top
 Profile  
Reply with quote  
PostPosted: Thu May 16, 2024 1:29 am 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8453
Location: Southern California
Since the last-compiled word tends to be an unnest (compiled by ;) and word-aligned, the beginning of my name fields is almost always aligned; so in that case, there are many cases when I know I can add another letter to the name if I want to, if it would make it more descriptive, without any memory penalty.

_________________
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?


Top
 Profile  
Reply with quote  
PostPosted: Thu May 16, 2024 2:00 am 
Offline

Joined: Fri May 05, 2017 9:27 pm
Posts: 864

In Fleet Forth nothing is word aligned. The only address adjustment is to make sure a page boundary is not straddled by the code field, and now the next four cells, of a word. I've not had any problems in Fleet Forth due to this lack of alignment.


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 343 posts ]  Go to page Previous  1 ... 19, 20, 21, 22, 23

All times are UTC


Who is online

Users browsing this forum: No registered users and 16 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to: