Page 16 of 19

Re: Tali Forth for the 65c02

Posted: Fri Dec 02, 2022 9:28 pm
by SamCoVT
Standard numbers in Tali are 16-bit so -32768 to +32767. If you use words like U. (u is for unsigned) to print the numbers, those same 16-bits can represent 0-65535 instead. There are other "unsigned" words like U< and U> to operate on unsigned values.

"Double" numbers in Tali use two 16-bit cells on the stack to make up a 32-bit number. This allows numbers from around -2.1 billion to +2.1 billion. You can deal with the halves as separate 16-bit values (most significant half is on top of stack) or use words like D. to print them and D+ to add them. To enter a double number, put a period after the last digit, eg: 1234567890.

Tali doesn't have the full double word set, but it has enough that all the "missing" words can be created if you need them. Here are some that I made while playing with FAT32 - some are ANS 2012 standard and some are just words I needed. In the stack comments, d = double, ud = unsigned double, n is a normal (signed 16-bit) number, u is an unsigned (16-bit) value, and f is a flag (true/false).

Code: Select all

\ Tali2 needs some extra double words.
: d=  ( d1 d2 -- f )
   rot = -rot = and ;
: d0=   ( d -- f ) 0= swap 0= and ;
: d0<>  ( d -- f ) or ;
: d2*   ( d -- f ) 2dup d+ ;
: d<    ( d -- f ) rot 2dup = if ( use LSBs ) 2drop <
   else ( use MSBs ) 2swap 2drop > then ;

: d0!  ( addr -- )  ( store double 0 at address )
   0. rot 2! ; allow-native
: d+!  ( d1 addr -- )  ( Add d1 to double at addr )
   dup >r 2@ d+ r> 2! ;
: d1+!  ( addr -- )  ( Add 1 to double at addr )
   1. rot d+! ;
There's also unsigned double words, like UD. that would print an unsigned double (values 0 to about +4.2 billion). Note that Forth expects the programmer to keep track of whether single or double values are on the stack and to use the appropriate words for them.

There are also 2CONSTANT and 2VARIABLE for constants and variables, 2DUP and 2DROP etc to manipulate them on the stack, etc. Most words that start with 2 (except 2* and 2/) work with double values. It's a bit unfortunate that some of the words start with 2 and others start with D, but that's how it is. You'll sometimes see the words used even with non-double values on the stack because (for example) 2DROP drops two items off the stack - it doesn't care if that was both halves of a double or two unrelated values.

Words that start with M are usually for "mixed" calculations, where one side is double and the other is not, eg M* (single value times a single value with a double result) and I bet you can figure out what UM* does now.

https://forth-standard.org, if you haven't found it already, will be very handy for reference as it covers the ANS 2012 Forth standard and I use the search function at the top all the time. The gotcha is that you kinda need to know the name of the word you want to know more about.

Re: Tali Forth for the 65c02

Posted: Fri Dec 02, 2022 9:45 pm
by SamCoVT
Snippets of example code using doubles:

Code: Select all

2variable sector# \ The disk sector currently in the buffer

\ Read sector (given as double) into sectorbuff.
: sector>buffer  ( sector#.d -- )
   ( See if we already have it in the buffer )
   2dup sector# 2@ d= if
      2drop exit ( already have this sector ) then
   2dup sector# 2! ( Remember this sector )
   sectorbuff -rot 1 -rot cf.read ( Read the sector ) ;

: finfo  ( fileid -- )  ( fileid info for debugging )
   cr ." FILEID: "          dup u.
   cr ." filename: "        dup >filename 0B type
   cr ." access mode: "     dup >attrib c@ u.
   cr ." first cluster: "   dup >firstcluster 2@ ud.
   cr ." current cluster: " dup >currentcluster 2@ ud.
   cr ." current sector: "  dup >currentsector 2@ ud.
   cr ." file position: "   dup >fileposition 2@ ud.
   cr ." file size: "       dup >filesize 2@ ud.
   cr ." linestart: "           >linestart 2@ ud. ;

Re: Tali Forth for the 65c02

Posted: Fri Dec 02, 2022 9:51 pm
by adrianhudson
Thank you both (leepivonka & Garth). I know about the scalar operators. but not about the floating point routines Garth, though they would be interesting to play with. I'm not convinced one would ever NEED floating point since scaled integer, as you say, can do pretty well anything floating point can do but it just needs more thinking about. I guess I need to think a little more about my current problem. I got an M24M02 eeprom today and replaced my smaller 24 chip. It works but the calculation of the addresses into it is overflowing and I need to rework the routines. I guess my question was more with thought for the future - whether there is a generalised way to deal with multi-cell arithmetic in Tali - ie. can an integer be held in 2 or more cells (obviously it can) and I was wondering out loud (without being too specific ) whether there are any boilerplate routines out there to work on these hypothetical multi-cell integers.
.
.
I notice while typing this that SamCoVT has also replied... (twice!)
...and has completely resolved my problem.

Thank you once again Sam.

Re: Tali Forth for the 65c02

Posted: Fri Dec 02, 2022 11:25 pm
by GARTHWILSON
adrianhudson wrote:
whether there is a generalised way to deal with multi-cell arithmetic in Tali - ie. can an integer be held in 2 or more cells (obviously it can) and I was wondering out loud (without being too specific ) whether there are any boilerplate routines out there to work on these hypothetical multi-cell integers.
.
.
I notice while typing this that SamCoVT has also replied... (twice!)
...and has completely resolved my problem.

I feel a bit out of place here since I'm not familiar with Tali specifically; but the double-precision material Sam presents has been standard Forth stuff for many decades, meaning it will be portable to other Forths as well.  I don't know how standard the triple- and quad-precision words I mentioned earlier might be.  There are UT*, UT/MOD, M*/MOD, Q/, D*/, Q+, Q!, Q@, Q2/, Q<, and others.

Quote:
To enter a double number, put a period after the last digit, eg: 1234567890.

The period can be anywhere, and variable DPL keeps track of how many digits were found to the right of the right-most decimal point in NUMBER? .  ANS might not use DPL.  I've had a little trouble figuring out how ANS handles the entry of double literals.  Sometimes I use the decimal point just for readability when I want for example 3.45 volts, where I don't really even need doubles, and I just reduce it to a single (just use DROP to do that) before using it.

Sam, please remind me of what "SamCoVT" stands for.  In my mind, I always say "Sam Covington;" but I know that's not right.

Re: Tali Forth for the 65c02

Posted: Fri Dec 02, 2022 11:33 pm
by adrianhudson
GARTHWILSON wrote:
I feel a bit out of place here since I'm not familiar with Tali specifically;
Thanks Garth.
What Forth do you use Garth? I've often wondered but much as I keep an eye out for you mentioning it as I read your primers and posts I have never spotted it.

Re: Tali Forth for the 65c02

Posted: Sat Dec 03, 2022 12:10 am
by GARTHWILSON
adrianhudson wrote:
GARTHWILSON wrote:
I feel a bit out of place here since I'm not familiar with Tali specifically;
Thanks Garth.
What Forth do you use Garth? I've often wondered but much as I keep an eye out for you mentioning it as I read your primers and posts I have never spotted it.
See viewtopic.php?p=96847#p96847 .

Re: Tali Forth for the 65c02

Posted: Sun Dec 04, 2022 11:09 am
by adrianhudson
SamCoVT, I'm getting on famously with Forth. Have implemented access of LCD and access if i2c devices. One thing that irritates is if you get it in a loop or other crash. The only way out is a reset button press. Is there any way Tali can be made to return to its internal main loop using NMI without reinitialising all its memory?
Edit: I guess what I am asking is, is there a warm restart point in the code?

Re: Tali Forth for the 65c02

Posted: Sun Dec 04, 2022 5:22 pm
by SamCoVT
GARTHWILSON wrote:
Quote:
To enter a double number, put a period after the last digit, eg: 1234567890.
The period can be anywhere, and variable DPL keeps track of how many digits were found to the right of the right-most decimal point in NUMBER? . ANS might not use DPL.
Since at least ANS94, the standard says the period goes on the end of the number, and I believe that's all Tali supports for entering double numbers (a quick test shows that Tali can only handle the . at the end). This may be to make it so it is distinct from floating point numbers, which some Forths support (but Tali does not - unless you add it yourself, of course). I did see DPL when playing with FIG-Forth, but apparently that was lost in the ANS standardization. I don't see it mentioned in the FORTH-83 standard at all, but I also don't see the . in numbers mentioned either.

Tali also supports base prefixes, which showed up in the 2012 ANS standard, so you can say (regardless of the current BASE):

Code: Select all

#123 \ 123 in decimal
$-123 \ -123 in hex
%101 \ 101 in binary
$12345678. \ a double in hex
GARTHWILSON wrote:
Sam, please remind me of what "SamCoVT" stands for. In my mind, I always say "Sam Covington;" but I know that's not right.
SamCo is a nickname I picked up in college because I was always building things. VT is because there are other SamCo's out there and I live in Vermont.

Re: Tali Forth for the 65c02

Posted: Sun Dec 04, 2022 5:25 pm
by leepivonka
Your NMI handler could re-enable interrupts then jmp to ABORT .

Re: Tali Forth for the 65c02

Posted: Sun Dec 04, 2022 5:36 pm
by SamCoVT
adrianhudson wrote:
One thing that irritates is if you get it in a loop or other crash. The only way out is a reset button press. Is there any way Tali can be made to return to its internal main loop using NMI without reinitialising all its memory?
Edit: I guess what I am asking is, is there a warm restart point in the code?
(leepivonka beat me to it but has an important extra piece of info - you need to re-enable interrupts) You could put the address for xt_abort in the NMI handler vector, I think. the ABORT word clears the data stack, clears the return stack, sets the input to the keyboard (serial port in your case), clears the input buffer, and goes into interpret mode so it will accept a new line and interpret it. The stacks will be gone, but any variables will be left alone, new words will still be in the dictionary, and your hardware should be where you left it because it won't have been reset (if it accepts the RESB signal).

At the end of your platform file, you will find the interrupt vectors. v_nmi is currently another name for kernel_init. You can change it to your own handler that re-enables interrupts and jumps to xt_abort. I haven't done this myself, so I'm not 100% sure this is a good solution, but I think it should work. NMI is falling edge triggered. Note that you won't get a new prompt (eg. cursor will be left wherever it is), but if you hit ENTER should should get the standard "ok".

Re: Tali Forth for the 65c02

Posted: Sun Dec 04, 2022 6:04 pm
by adrianhudson
Thank you both. I changed the platform file from

Code: Select all

v_nmi:
v_reset:
;v_irq: ; IRQ redirected to SERVICE_ACIA
kernel_init:
to

Code: Select all

v_nmi:
		pla
		pla
		pla
		cli
		jmp xt_abort
v_reset:
;v_irq: ; IRQ redirected to SERVICE_ACIA
kernel_init:
...which seems to work. Fantastic! Even if it doen't work under all conditions (which I have yet to determine), it is better than nothing.

Re: Tali Forth for the 65c02

Posted: Mon Dec 05, 2022 4:45 pm
by SamCoVT
adrianhudson wrote:

Code: Select all

v_nmi:
		pla
		pla
		pla
		cli
		jmp xt_abort
v_reset:
;v_irq: ; IRQ redirected to SERVICE_ACIA
kernel_init:
Just FYI, you don't need to bother with the pla instructions, as xt_abort resets the return stack (along with the data stack). It's designed so that you can abort from the middle of a loop in a loop in a loop or deeply nested words and it will reset everything to base levels and go back to interpreting.

Re: Tali Forth for the 65c02

Posted: Mon Dec 05, 2022 5:02 pm
by adrianhudson
Oh, thanks for that, will change it...
It works very reliably. It's useful as I am messing with a permanently running app (just a clock reading from as ds3231). (What I really want is a background Forth task. I read somewhere that some Forths have that).

Re: Tali Forth for the 65c02

Posted: Mon Dec 05, 2022 8:06 pm
by SamCoVT
Some Forths support tasking. Tasking was on Scot's wishlist for Tali Forth 2. Some of the work has been started to support it (moving things to user variables accessed via a base "user pointer") but it's likely that more would have to be moved around to be ready for full tasking support. You can read about our musings on it here: https://github.com/scotws/TaliForth2/issues/234

If you wanted to do an interrupt based background task (based on one of your 65C22 timers, for example), you should be able to do that, but would need to take extra care. You would need to save/restore A and Y (X is used for the data stack and you could use it if you made sure it was at the same value when done), and you'd likely also need to save/restore tmp1, tmp2, and tmp3, which are locations in zero page (two bytes each) used to hold data temporarily; they are used by many words who expect they are the only one using them. You can find their definitions in definitions.asm. To find their exact locations, you'll need to know where user0 is (they are defined as offsets from that address) and that's in your platform file. user0 is usually address 0 in zero page, but Tali lets you move the entire block of variables in zero page by changing user0 in your platform file.

If that's the kind of rabbit hole you'd like to go down, I'd be interested in what you find. You're welcome to start a new thread to chronicle your adventures/progress and report what does (and doesn't) work.

Re: Tali Forth for the 65c02

Posted: Mon Dec 05, 2022 10:46 pm
by adrianhudson
SamCoVT wrote:
If you wanted to do an interrupt based background task (based on one of your 65C22 timers, for example)
Umm, forth or assembler? I doubt I am up to coding an interrupt routing in forth yet!

While I am here, can I ask: I have been coding away in Forth and pasting the code into my terminal program. Eventually Tali crashes. On investigation I suspect the dictionary grows with old versions of words as I edit/test/edit/test until Tali crashes. Is this your expectation or is there something else going on do you think? Do all Forths just grow or do some have housekeeping? I guess that would be non-trivial.