• Please review our updated Terms and Rules here

Epson HX-20 - FORTH ROM

Martin,

For your information, I attach the text for the disk words I created.

The first screen is the working set. The second screen is a reduced few, the idea was that I'd have these on a tape to load, which would then allow the loading of the full set from disk. The third screen is some extra bits I was working on, i.e. the D-RESET etc, but I don't think I even tested these.

All this text is recovered from the file on the floppy disk that it was saved to using D-SAVE years ago. I still have the disk with the file on. If you want to try it, I could create a .WAV version of the main (first) screen.

I've no doubt that my code could be better, but I was just trying to get it working. Then I never got around to improving it!
 

Attachments

  • DISK.TXT
    3.1 KB · Views: 11
In that regard, Forth is the other Lisp. I tried to bring that aspect across in some of my Forth videos. It's a fascinating language.
It is often hard to unlearn once exposed to things like BASIC or C. I've done some LISP but find it harder to debug. I do like the ability to apply math operators across an entire string. It removes the concept the + needs to start with 2 values and then one additional + for each additional value. There is something that just seems more right in LISP.
Both languages do have the simplified "write a small amount of code and test it" type of coding that makes it much faster to generate working code.
In Forth, some like having a special comment word that embeds the test code right in the source, like a comment. Then one can set a special interpreter/compiler flag to have it execute the test code on one of the compile passes. Keeping the stack balanced is the hardest thing to learn when first learning.
I've not done this myself but saw it done once. An interesting way of making self checking code.
Dwight
 
In Forth, some like having a special comment word that embeds the test code right in the source, like a comment. Then one can set a special interpreter/compiler flag to have it execute the test code on one of the compile passes. Keeping the stack balanced is the hardest thing to learn when first learning.
Right, the idea to use the same language at compile time (using IMMEDIATE words), and at runtime, is something that is not appreciated enough. Basically, Forth words can be executed a COMPILE time to compute the definitions of the word you are currently compiling - compiler extensions in the language *itself* (rather than a preprocessor- or "outside" language). In Common Lisp, we have macros for that. Many aspects of (Common) Lisp, such as defmacro, Backquote, Comma, Quasi Quote, and Metaprogramming, directly apply to Forth as well. For starters, Words are analog to Symbols in Lisp. Heck, even Quote (= Tick ' in Forth) and Comma (= , in both) basically have the same semantics in both Forth and Lisp! Albeit known under different terms. But the basic ideas are similar. Some folks use the word "homoiconicity" these days, but I am not sure that's a good fit for Forth. Lisp has been coined a "programmable programming language". The same applies to Forth. I am pretty sure that Charles Moore (inventor of Forth) was well aware of Lisp... but wanted something more lightweight, and without expensive runtime system for Garbage Collection and what have you. My suspicion is that when HP created RPL (Reverse Polish Lisp) for their calculators, the combined Forth and Lisp basically.

EDIT: I should say that all of this is speculative, and I haven't read anything about Lisp influencing Forth's design on any official historical narratives. If anybody has interviews, or other historical "footage" that would confirm these (to me blatantly obvious cross-pollination from Lisp) then I'd be very interested to hear about that.
 
Last edited:
Martin,

For your information, I attach the text for the disk words I created.

[...]
Geoff,

thank you for your kind WORDs.

I looked at them and disassembled them to understand what you actually did.
Very nice - obviously, you went deep into the system at the time.

I did not try them yet, but instead added two new words to the ROM:
SERPWR allows powering the standard RS232C port on and off and SEROUT outputs a byte to the RS232C port.
For simplicity, I hardcoded the port settings at 4800,8,n,1 without handshaking, so a slow printer would need delay loops.

Additionally I enhanced the existing PRINT word so that one can now output to the internal printer as before and/or to the RS232C port.
This produces a nice VLIST or readable screen editor listings on a terminal (Teraterm on my laptop).
One could even think of writing e.g. a tic-tac-toe game with "full screen" output on a terminal, using escape sequences.

I did not implement any serial input words, as this requires a buffer and I am not sure yet where to place this (maybe use PAD, allocate something in the dictionary or use the tape buffer?)
The "high speed" serial port is still left e.g. for mass storage or display controller.

A few bytes of ROM space are still left...

In the meantime I also obtained a "new" keyboard PCB, where only the "]" does not work - at least better than before.

I'll post an update when "everything is finished" (famous last words).
Martin
 
Right, the idea to use the same language at compile time (using IMMEDIATE words), and at runtime, is something that is not appreciated enough. Basically, Forth words can be executed a COMPILE time to compute the definitions of the word you are currently compiling - compiler extensions in the language *itself* (rather than a preprocessor- or "outside" language). In Common Lisp, we have macros for that. Many aspects of (Common) Lisp, such as defmacro, Backquote, Comma, Quasi Quote, and Metaprogramming, directly apply to Forth as well. For starters, Words are analog to Symbols in Lisp. Heck, even Quote (= Tick ' in Forth) and Comma (= , in both) basically have the same semantics in both Forth and Lisp! Albeit known under different terms. But the basic ideas are similar. Some folks use the word "homoiconicity" these days, but I am not sure that's a good fit for Forth. Lisp has been coined a "programmable programming language". The same applies to Forth. I am pretty sure that Charles Moore (inventor of Forth) was well aware of Lisp... but wanted something more lightweight, and without expensive runtime system for Garbage Collection and what have you. My suspicion is that when HP created RPL (Reverse Polish Lisp) for their calculators, the combined Forth and Lisp basically.

EDIT: I should say that all of this is speculative, and I haven't read anything about Lisp influencing Forth's design on any official historical narratives. If anybody has interviews, or other historical "footage" that would confirm these (to me blatantly obvious cross-pollination from Lisp) then I'd be very interested to hear about that.
When I was first exposed to Forth it took some time to fully grasp the <BUILDS DOES> construct. It was so alien to anything in programming I'd been exposed to before. It is the best way to get the grasp of compile time versus run time. Once one fully understands how it works, it seems like other languages missed the true meaning of full programming of a computer. Forth then becomes an open ended language.
Dwight
 
When I was first exposed to Forth it took some time to fully grasp the <BUILDS DOES> construct. It was so alien to anything in programming I'd been exposed to before. It is the best way to get the grasp of compile time versus run time. Once one fully understands how it works, it seems like other languages missed the true meaning of full programming of a computer. Forth then becomes an open ended language.
Dwight
I'm not a fan of garbage collection. I think it is one of the most dangerous things put into languages today. In real time uses it can downright kill people. Imaging a severely fragmented memory. The detector just found an object flying at you at hyper speed and you need a 4 denominational array to track its trajectory. But, wait a moment, I need to first rebuild the memory for you to use, I'll BE RIGHT BACK!
Dwight
 
Which is why dynamic memory allocation is not permitted in safety critical applications (I will qualify that by ‘after initialisation’ though). There is then no need for any garbage collection...

Dave
 
Understood. I think both languages with and without GC have their applications... GC is there to stay these days. And then there is the school of thought saying that memory management (requiring malloc, free, and pointers...) is simply too difficult to get right for the ordinary programmer... so the computer should do it.

Modern GC is also typically pretty fast... and not as disruptive to runtime operations as it used to be (unless you have garbage maker programs of course). E.g., Common Lisp uses ephemeral and concurrent GC these days AFAIK. But it used to be pretty bad, especially in BASIC. The first Amstrad CPC BASIC had a bug related to GC and strings... even caused by string printing... resulting in wait times of up to 40 minutes if you wanted to open a file. There was a simple workaround though, and it got fixed in the next version of Locomotive BASIC (1.1).
 
After squeezing a few more unused bytes out of the HX-20 Forth ROM, it has now been enhanced with words to read and write bytes over the RS232C interface at 4800 baud. Using an enhanced PRINT word I can now redirect a copy of the LCD character output to the internal printer and/or to my laptop via RS232C.
This is very convenient e.g. when doing a VLIST or editing and listing a screen. I can also send text from the laptop to the HX-20 and e.g. display it on screen or perform some action on it. Thus the HX-20 can be used as a powerful coprocessor to the laptop - Hah!

@geoff: could you look up the "H" Editor keyword in your manual? I understood that e.g. "2 H" should copy line #2 of the currently edited screen to the PAD, and the source code looks like it is doing that. But PAD seems to stay empty. I am probably doing something stupid here.

An update will be made available after the EPROM burner has cooled down (I never erased and burned so many cycles into a pair of EPROMS before, probably need a RAM-based EPROM emulator).

Martin
 
Martin,

I don't think I ever got around to using H, or PAD. If I made mistakes, I just re-entered, didn't mess about too much.

Yes, the manual says that H - Hold text of the given line at PAD. The line also remains in the screen.

Then 2 RPAD will put the text in PAD to line 2 of the screen.

How are you looking at what is in PAD? PAD seems to be a very temporary buffer.

IPAD inserts the text into the screen, moving other lines down. RPAD replaces the line with the text from PAD, so I assume that what WAS there it lost.

Geoff
 
@geoff: I thought that when I "L"ist a screen, the content of PAD is listed at the end after a "#" character for "cursor editing".
But maybe I did something wrong. Have to give it a try in the evening, maybe following your "2 H" " 3RPAD" or "2 H" "3 IPAD" examples.

Thank you for the hints.
Martin
 
I don't see any mention of that in my manual. L just lists the current screen. No mention re PAD.

When you start a screen, the system displays a blank screen. I've got a handwritten note there to say 'extra bit is PAD' but this may be a reference to the reference to the editor memory being &710 to &B20 which is 16 bytes more than 1k?? Actually, another part of the manual says that the editor/screen memory is &710 to &B30 which is 32 bytes more?

FORTH does not seem to make any attempt to use the Virtual Screen facilities of the HX, it would be a help if it did. The screen is never more than 80 chars (i.e. 4 lines of 20). I've got another written note saying Virtual Screen &2D0 (80 bytes) - but a virtual screen capable of handling 16 lines of 64 chars would be a massive help.

Geoff
 
o:k: the words H, IPAD and RPAD, of course, work as advertised - I had believed that the word L would list the PAD after line 15 (separated by a #) which was wrong. The # is the string editor cursor which can be used with the line oriented cursor commands.
I now also use the book "FORTH for the B.B.C. Microcomputer", also written by the same author (Joseph W. Brown) as a reference.
 
Finally I'll post the LATEST version of my modified Forth ROM HERE.

The last addition was the ASCII word to simplify the input of single character codes.
Also PRINT has been enhanced further to allow any combination of output to none/LCD/printer/RS232C.

Martin
 

Attachments

  • Epson-HX20-Forth-ROM-Source.zip
    1 MB · Views: 16
Excellent work, looking forward to trying this at some point! Btw, I would offer you my (fully working) US replacement keyboard - but I am in the US, so you would have to pay ~20 USD for shipping...
 
@LambdaMikel: than you for your offer - luckily, I already found a "new" keyboard here in Europe where only one key has trouble and another hopefully fully working one is on its way. Today I also had to replace the still original microcassette belt which started to slip (no surprise).
These old machines always need some love.

and the latest BYTE Sieve Benchmark results are

Computer
Year
CPU Type and Speed
Programming Language
Time
HX-20​
1982​
6301 @ 614 kHz​
BASIC​
4050 s​
HX-20​
1982​
6301 @ 614 kHz​
Assembler​
17 s​
HX-20​
1982​
6301 @ 614 kHz​
Forth​
229 s​
TI-99/4​
1981​
TMS 9900 @ 3.0 MHz​
TI-BASIC​
3960 s​
PET​
1977​
6502 @ 1.0 MHz​
BASIC​
3180 s​
Apple ][​
1977​
6502 @ 1.02 MHz​
Applesoft BASIC​
2806 s​
HP-85​
1980​
Capricorn @ 625 kHz​
BASIC​
3084 s​
HP-85​
1980​
Capricorn @ 625 kHz​
Assembler​
21 s​
TRS-80/II​
1977​
Z-80 @ 1.0 MHz​
MBASIC​
2250 s​
IBM PC​
1981​
8088 @ 4.77 MHz​
BASICA​
1990s​
Martin
 
Last edited:
Cool - do you have the Sieve FORTH benchmark somewhere? Prime numbers I suppose? I did a BASIC version for the HX-20 at some point 😀 What's the limit for the sieve here? My simple BASIC program does up to 500 in 17 seconds on the HX20:

 
The source code in various languages as well a a list of results can be found in BYTE Magazine September 1981 with a revision in January 1983 (e.g. at archive.org).

Their benchmark determines all primes between 0 and 2*8192 (skipping the even numbers) and repeats this 10 times for obtaining the final time.
Note that the goal of this simple benchmark is not to optimize the sieve algorithm for a given system but to compare the same algorithm in different languages on different systems.
The Forth code has two small errors (comparison should be "<=" instead of "<" and flag array size is 1 off), so that I adapted the code slightly, but that should not affect timing too much.

Martin
 
This is the last update with the "final" version of my re-built ROM and proofread documentation. I found a few more unused bytes which allowed to add a 2/ word.
 

Attachments

  • Epson-HX20-Forth-ROM-Source.zip
    1.3 MB · Views: 14
Hi Martin
There are people that consider the first element of an array as element 1 and some that consider it as element 0. I've see them implemented both ways but I of course prefer 0 as the first element.
I work with code that was written for ATPG (Atomatic Test Pattern Generation ) and they use 1 based arrays. Go Figure.
Dwight
 
Back
Top