Jump to content

TheBF

+AtariAge Subscriber
  • Posts

    4,470
  • Joined

  • Last visited

Everything posted by TheBF

  1. The great thing about today's TI-99 programmer is Classic99's ability to take pasted text. You can have great fun just using text files for your programs and pasting them into the emulator at blazing speed. I am working again here with floppy drives and I wish they had a "Viagra" for their floppy-ness. It is slooooowwww.
  2. You are perfectly correct. TO in LOGO is like : in Forth. I think Forth was first. It was one guy who made it for himself in 1969 ish. and then developed it over the next few years. It was a stack of punched cards in the beginning. https://www.forth.com/resources/forth-programming-language/
  3. Forth is a lot like learning a human language. Lots of words each with a specific meaning. BUT... you can change it as you go.
  4. Turbo Forth doesn't have the word ?terminal. It is telling you that in error message. I think you make it though. : ?TERMINAL KEY? 2 = ;
  5. I suppose it would be wrong to leave out just how configurable Forth is. You are free to make DO/LOOP yourself in a different way if you really want to dig into how the compiler is built. Or you could just add ?BREAK to the existing LOOP routine like this. (tested with FbForth) COMPILE is used for ordinary (non-immediate) Forth words. [COMPILE] is used to "compile" IMMEDIATE words. Now when you use LOOP in a definition it will first COMPILE the address of ?BREAK followed by the address of LOOP ; In other words you have changed the compiler! You could do the same thing with AGAIN, UNTIL and REPEAT. If you made a block with these words in it, you could load it first for testing programs. Then all you loops would be "breakable". Then re-compile without the breakable loops and run at full speed. \ breakable loop : ?BREAK ?TERMINAL ABORT" *BREAK*" ; : LOOP COMPILE ?BREAK [COMPILE] LOOP ; IMMEDIATE \ test it : STAR 42 EMIT ; : STARS ( n -- ) 0 DO STAR LOOP ; 20000 STARS ( hit fctn 4 when you get tired of it) Note:For ANS Forth like CAMEL99 Forth change LOOP to: : LOOP POSTPONE ?BREAK POSTPONE LOOP ; IMMEDIATE
  6. Forth words are built on the idea that each routine should do one thing. You will find therefore that LOOP etc. have no way out. But it is simple to add. The word ?TERMINAL reads the F4 on the TI and returns true if it is pressed. So you could do this: : ?BREAK ?TERMINAL ABORT" BREAK KEY DETECTED!" ; Add the word ?BREAK anywhere that you think you might want to stop the program.
  7. Who needs string comparison case statements? In the course of porting an editor to TTY over RS232 I bumped into the challenge of escape key sequences. One way to do it is to read the sequences into strings and then compare the strings to other strings to determine which control sequences was sent from the terminal. However... It occurred to me that a faster way to do it would be to hash the characters sequence into a unique number and then use a regular integer case statement to do the correct action. The sequences are short so the overhead to hash the string is small. Here is what I came up with to test the concept. Since the sequences are variable I use TKEY to wait for each character. TKEY will read a key or return zero if the key does not arrive in time. Then for the 2nd, 3rd and 4th character I multiply the ascii value by a different value. Actually I just do 3 different shifts. I tried just summing the ascii values but I could not differentiate the keys F9..F12 from the F1 to F4 keys without doing the multiply operations. The longest string is 4 chars but I got cleaner read by adding a 5th TKEY. When a key is held down this reader would get out of sync and generate a single ascii character which would go into the text of the editor if I left it there. The extra TKEY cleaned that up. The first KEYHANDLER reads normal control keys with single value output. If it detects the ESC key it calls the ESCHANDLER to deal with the control sequence. The short video demonstrates this test code. \ Esc sequence decoder using hashing NEEDS CASE FROM DSK1.CASE MARKER REMOVE HEX 1B CONSTANT [ESC] : TKEY ( wait-time -- 0 | c ) \ waits for a key -or- until counter hits zero BEGIN 1- DUP WHILE CKEY? ?DUP IF NIP EXIT THEN REPEAT ; DECIMAL : HASHKEY ( -- n) 75 TKEY 75 TKEY 2* 75 TKEY 4* 75 TKEY 8* 75 TKEY \ dummy read + + + + ; \ 5 timed reads & sum HEX : ESCHANDLER ( -- ) HASHKEY CASE \ TESTED 02B5 OF ." HOME " ENDOF \ PC Home 02B7 OF ." INSERT " ENDOF \ PC Insert 02BB OF ." END " ENDOF \ PC End 02BD OF ." PGUP " ENDOF \ PC Page up 02BF OF ." PGDN " ENDOF \ PC Page down 00DD OF ." UPARROW " ENDOF \ PC up arrow 00DF OF ." DNARROW " ENDOF \ PC down arrow 00E1 OF ." RIGHT " ENDOF \ PC right arrow 00E3 OF ." LEFT " ENDOF \ PC left arrow 010F OF ." -TAB " ENDOF \ PC shift TAB \ PC function keys 0571 OF ." FCTN1 " ENDOF 0575 OF ." FCTN2 " ENDOF 0579 OF ." FCTN3 " ENDOF 057D OF ." FCTN4 " ENDOF 0581 OF ." FCTN5 " ENDOF 0589 OF ." FCTN6 " ENDOF 058D OF ." FCTN7 " ENDOF 0591 OF ." FCTN8 " ENDOF 056F OF ." FCTN9 " ENDOF 0573 OF ." FCTN10 " ENDOF 057B OF ." FCTN11 " ENDOF 057F OF ." FCTN12 " ENDOF ENDCASE ; : KEYHANDLER ( char -- ) \ VT100 TERMINAL key codes CASE [ESC] OF ESCHANDLER ENDOF \ if we get ESC key [CHAR] A OF ." A " ENDOF [CHAR] B OF ." B " ENDOF [CHAR] C OF ." C " ENDOF 9 OF ." TAB " ENDOF 3 OF CR QUIT ENDOF \ ^C 7 EMIT \ key not found, ring the bell ENDCASE ; HEX : TEST KEY HASHKEY . ; : TESTHASH BEGIN KEY KEYHANDLER AGAIN ; HASH_CTRL_KEYS.mp4
  8. VT100 driver Change While working on porting an editor to TTY control I did a re-read of the control code specs and discovered that the terminal assumes cursor home is coordinates (1,1). Standard Forth AT-XY (and GOTOXY in TI-Forth, FbForth and TurboForth) assumes home is (0,0). I have modified a couple of words in my code to compensate. This has made my porting of the editor code way easier. The word AT-XY is modified below: CR .( VT100 terminal control, [0,0] Home coordinates May 2020 ) DECIMAL \ type 'n' as a two digit number in base 10, with no space : <##> ( n -- ) BASE @ >R \ save radix 0 <# DECIMAL # # #> TYPE \ convert to 2 digits & print R> BASE ! ; \ restore radix \ markup language for terminal control codes : <ESC> ( -- ) 27 EMIT ; : <ESC>[ ( -- ) <ESC> 91 EMIT ; : <UP> ( n -- ) <ESC>[ <##> ." A" ; : <DOWN> ( n -- ) <ESC>[ <##> ." B" ; : <RIGHT> ( n -- ) <ESC>[ <##> ." C" ; : <BACK> ( n -- ) <ESC>[ <##> ." D" ; : <HOME> ( -- ) <ESC>[ ." H" 0 0 VROW 2! ; \ define Forth words using markup words : PAGE ( n -- ) <ESC>[ ." 2J" <HOME> ; : AT-XY ( col row --) 2DUP VROW 2! \ store col,row <ESC>[ 1+ <##> ." ;" 1+ <##> ." f" ; And the word <SCROLLROWS> below has been correct to reflect 0,0 screen home. <SCROLLROWS> is pretty cool. It lets you set a section of the screen that scrolls between rstart row and rend row. CR .( VT100+.FTH extended terminal control) NEEDS <##> FROM DSK1.VT100 DECIMAL \ reset the terminal, clear screen & buffer : <RESETVT100> ( -- ) <ESC> [CHAR] c EMIT ; \ More VT100 terminal controls : <SCROLLALL> ( -- ) <ESC>[ ." r" ; \ Enable scrolling for entire display. \ Enable scrolling from row {start} to row {end}. [0,0] IS HOME !! : <SCROLLROWS> ( rstart rend-- ) SWAP <ESC>[ 1+ <##> ." ;" 1+ <##> ." r" ; : <SCROLLDOWN> ( -- ) <ESC> [CHAR] D EMIT ; \ Scroll display down one line. : <SCROLLUP> ( -- ) <ESC> [CHAR] M EMIT ; \ Scroll display up one line. \ Erasing Text : <ERASERIGHT> <ESC>[ ." K" ; \ Erase from cursor to end of line : <ERASELEFT> <ESC>[ ." 1K" ; \ Erase from Cursor to start of line : <ERASELINE> <ESC>[ ." 2K" ; \ Erases the entire current line : <ERASEDOWN> <ESC>[ ." J" ; \ Erases screen from current line down : <ERASEUP> <ESC>[ ." 1J" ; \ Erases screen from current line up
  9. To be sure I was abiding by this I checked. Camel99 enters it's first code to create the virtual machine. (set workspace, init 3 registers, write some code into scratchpad and init 1 memory location) Interrupts are off by default from E/A 5 as mentioned. I don't enable interrupts until I start Forth and load a value into the 9901 timer. When that code exits it enables interrupts. So more by ignorance than design, back when I made this thing I did follow this advice.
  10. Thank you for the clarification. I always appreciate your details.
  11. I think Lee has clarified "normal" from the sacred text, so please don't change your code on my account. I am the wild card. I have re-built and reverted back to using the 9901 timer which is how it was since Version 2 of this project began. That gave some problems in Classic99 at one point but it has long since been fixed. My motivation for these step-wise changes has been exploring removing bytes from the kernel to have more space for user programs. I think I am at the end of that exercise. If it ain't broke etc...
  12. That manual is a real gold mine. In the release that JediMatt tested I was not reading the screen timer but rather the random number seed at >8379, which continues spinning on one byte with the E/A cartridge. Could it be that TI BASIC changes that location or stops incrementing it when it starts? I will have to check that here. Nevertheless it was a test version to see if that would work better than the 9901 timer. I should think that the timer is a better strategy for general use.
  13. To confirm: This version is using the interrupt driven counter at >8379 to time how fast to blink the cursor. It looks like TIPI disables this counter. (?) If I send you the version that uses the 9901 timer could I trouble you to try that one?
  14. Thank you! So that points perhaps to the way that I am doing blinky part and how it interacts with other hardware. I explored two methods. One uses the 9901 timer the other uses the interrupt driven counter in scratch pad RAM. I have to double back and check which method is used in that version, but I believe it is the 9901 timer which I have running continuously. If the other hardware is blocking the timer somehow that would stop the blinky thing. Thanks again for the testing.
  15. I am always happy to hear about someone digging into Forth. No reason for just a few of us to back talkwards around here. If you have any spare band-width could I ask you try to start Camel99 Forth on a TIPI drive. **Not to replace FBForth** (which has far better documentation for the novice) I just don't have TIPI and want to know if it works. You can get a current version here. You really only need DSK1. or even less just the files CAMEL99 START and SYSTEM just to see if it boots and loads the startup stuff. No rush or pressure. I am just curious for a simple test by someone on this fancy new hardware. Thanks in advance. B
  16. In the process of fighting with making an editor for the VT100 terminal I looked into what features I had. I have a simple file that compiles on startup with the TTY version of Camel99 Forth that gives cursor positioning, clearing the screen as well some basic cursor movements. I took the approach of creating a tag type language for this lexicon so the VT100 words stand out from other Forth words. Kind of HTMLish. CR .( VT100 terminal control) DECIMAL \ type 'n' as a two digit number in base 10, with no space : <##> ( n -- ) BASE @ >R \ save radix 0 <# DECIMAL # # #> TYPE \ convert to 2 digits & print R> BASE ! ; \ restore radix \ markup language for terminal control codes : <ESC> ( -- ) 27 EMIT ; : <ESC>[ ( -- ) <ESC> 91 EMIT ; : <UP> ( n -- ) <ESC>[ <##> ." A" ; : <DOWN> ( n -- ) <ESC>[ <##> ." B" ; : <RIGHT> ( n -- ) <ESC>[ <##> ." C" ; : <BACK> ( n -- ) <ESC>[ <##> ." D" ; : <HOME> ( -- ) <ESC>[ ." H" 1 1 VROW 2! ; \ define Forth words using markup words : PAGE ( n -- ) <ESC>[ ." 2J" <HOME> ; : AT-XY ( col row --) ( uses base 0 coordinates) 2DUP VROW 2! \ store col,row <ESC>[ <##> ." ;" <##> ." f" ; Here are some scrolling controls. I have created separate files to save space in a program that doesn't need everything. CR .( VT100+.FTH extended terminal control) NEEDS <##> FROM DSK1.VT100 DECIMAL : <RESETVT100> ( -- ) <ESC> [CHAR] c EMIT ; \ reset the terminal : <SCROLLALL> ( -- ) <ESC>[ ." r" ; \ Enable scrolling for entire display. \ Enable scrolling from row {start} to row {end}. : <SCROLLROWS> ( rstart rend-- ) SWAP <ESC>[ <##> ." ;" <##> ." r" ; : <SCROLLDOWN> ( -- ) <ESC> [CHAR] D EMIT ; \ Scroll display down one line. : <SCROLLUP> ( -- ) <ESC> [CHAR] M EMIT ; \ Scroll display up one line. \ Erasing Text : <ERASERIGHT> <ESC>[ ." K" ; \ Erase from cursor to end of line : <ERASELEFTS> <ESC>[ ." 1K" ; \ Erase from Cursor to start of line : <ERASELINE> <ESC>[ ." 2K" ; \ Erases the entire current line : <ERASEDOWN> <ESC>[ ." J" ; \ Erases screen from current line down : <ERASEUP> <ESC>[ ." 1J" ; \ Erases screen from current line up And here is some color control CR .( VT100COLR.FTH Display Attribute control lexicon) \ BJF May 2020 NEEDS <##> FROM DSK1.VT100 DECIMAL \ colors 0 CONSTANT BLK 1 CONSTANT RED 2 CONSTANT GRN 3 CONSTANT YEL 4 CONSTANT BLU 5 CONSTANT MAG 6 CONSTANT CYN 7 CONSTANT WHT : <ATTRIB> ( n -- ) <ESC>[ <##> ." m" ; \ Usage: BLK <FG> CYN <BG> : <FG> ( color -- ) 30 + <ATTRIB> ; \ convert to foreground value : <BG> ( color -- ) 40 + <ATTRIB> ; \ convert to background value \ attributes : <DEFAULT> 0 <ATTRIB> ; : <BRIGHT> 1 <ATTRIB> ; : <DIM> 2 <ATTRIB> ; : <UNDERSCORE> 4 <ATTRIB> ; : <BLINK> 5 <ATTRIB> ; : <REVERSE> 7 <ATTRIB> ; : <HIDDEN> 8 <ATTRIB> ; Here is some test code and a little video : A$ S" This sentence will be displayed with different attributes." ; \ TEST CODE : TESTBG CR 8 0 DO I <BG> A$ TYPE CR LOOP <DEFAULT> CR ; : TESTFG CR 8 0 DO I <FG> A$ TYPE CR LOOP <DEFAULT> CR ; : TESTATTRIB CR 8 0 DO I <ATTRIB> A$ TYPE CR LOOP <DEFAULT> CR ; VT100control in Forth.mp4
  17. I was reading about and tried this program to generate Morse code on the TI-99. I thought some would find it interesting to see how you could do it in Forth. I wrote this up for Rosetta Code a few years ago for a PC so here it is ported to Camel99 Forth. In this method each letter of the Alphabet becomes a Forth program that knows how to send it's own Morse code sound. The Transmit routine reads each character in a string and interprets them. A rather different approach. \ MORSE CODE GENERATOR for Rosetta Code Brian Fox, Feb 2016 \ Ported to Camel99 Forth May 2020 NEEDS VALUE FROM DSK1.VALUES NEEDS SOUND FROM DSK1.SOUND NEEDS FORGET FROM DSK1.FORGET DECIMAL 750 VALUE FREQ \ 750 Hz will be the tone freq. 200 VALUE ADIT \ duration of one "dit" \ Compute all durations based on ADIT : DIT_DUR ADIT MS ; : DAH_DUR ADIT 3 * MS ; : WORDGAP ADIT 5 * MS ; : OFF_DUR ADIT 2/ MS ; : LETTERGAP DAH_DUR ; \ space between letters is commonly a DAH. : TONE ( -- ) FREQ HZ 0 DB ; : MORSE-EMIT ( char -- ) DUP BL = \ check for space character IF DROP WORDGAP \ ignore char and delay ELSE PAD C! \ write char to buffer PAD 1 EVALUATE \ evaluate 1 character string LETTERGAP THEN ; : TRANSMIT ( ADDR LEN -- ) CR \ newline, BOUNDS \ convert loop indices to address ranges DO I C@ DUP EMIT \ dup and send char to console MORSE-EMIT \ send the morse code LOOP ; \ dit and dah define all the reset : . ( -- ) TONE DIT_DUR MUTE OFF_DUR ; : - ( -- ) TONE DAH_DUR MUTE OFF_DUR ; \ define morse letters as Forth words. They transmit when executed : A . - ; : B - . . . ; : C - . - . ; : D - . . ; : E . ; : F . . - . ; : G - - . ; : H . . . . ; : I . . ; : J . - - - ; : K . - . ; : L . - . . ; : M - - ; : N - . ; : O - - - ; : P . - - . ; : Q - - . - ; : R . - . ; : S . . . ; : T - ; : U . . - ; : V . . . - ; : W . - - ; : X - . . - ; : Y - . - - ; : Z - - . . ; : 0 - - - - - ; : 1 . - - - - ; : 2 . . - - - ; : 3 . . . - - ; : 4 . . . . - ; : 5 . . . . . ; : 6 - . . . . ; : 7 - - . . . ; : 8 - - - . . ; : 9 - - - - . ; : ' - . . - . ; : \ . - - - . ; : ! . - . - . ; : ? . . - - . . ; : , - - . . - - ; : / . . . - . - ; ( SK means end of transmission in int'l Morse code) : . . - . - . - ; ( ~ 10 words per minute ) S" CQ CQ CQ DE VE3CFW / " TRANSMIT Note: I am getting different timing on Classic99 versus real iron. Hmm... ? This was my mistake. They both run at the same speed but... the real iron timing using the 9901 is more precise than Classic99 under windows. (to be expected) On the real hardware the letters are crisp and accurate every time even at morse code speeds of 20 WPM. Camel99 Forth's timer word MS, shines on real hardware.
  18. Sometimes the world presents us with strange coincidences A while back I added a string comparator to the CASE statement in Forth just to see what it would take. I am working on porting my SAMS editor to a VT100 terminal and guess what I need? A way to parse escape strings and run code. On the VT100 terminal when you press Page-up, Page-down or the cursor keys for example, the terminal emits a string of key-strokes. For example PAGE-UP emits: <ESC>[6~" Where <esc> is HEX 1B. So if you detect the escape character you then have to collect the next three characters as a string. That string needs to be compared to a table of strings to know what to do. Now the Forthy way to do this might be to make Forth words called [6~, [5~ etc. This way the Forth language would just run the routine like any Forth word. It could even compile that routine into other routines. The only trouble with that is we encounter an unknown sequence of characters Forth will Abort to interpreter. There are some solutions to that problem but I will leave that for later. Here is what I came up with that seems to work but I suspect it will not be fast. It revolves around code I developed to allow me to upload text files to disk with out using XMODEM. TIMEKEY is routine that waits for a key until a specific time elapses. I need this because the length of the escape sequences is variable. You never know how many characters you are waiting for exactly. STRAIGHT is the end user word to read data into a buffer & lenght set of input parameters and it returns the number of characters received. READSEQ puts them all together and put the string in PAD as a counted string which can be fed to the CASE statement. The case statement is for testing and just prints the name of the code it will run in the final application. I did not count on this much trouble to build an editor for a VT100/ANSI terminal. : STRAIGHT ( addr len -- n) 0 -ROT \ char counter under address OVER >R \ save the 1st buffer location 1 /STRING BOUNDS ( -- end start) R> ( -- end start addr) KEY SWAP C! \ wait for 1st key & store DO 100 TIMEKEY DUP I C! 0= IF 1+ LEAVE THEN 1+ LOOP ; CREATE SEQ$ 8 ALLOT \ returns a counted string : READSEQ ( -- Caddr) SEQ$ DUP 4 STRAIGHT PAD PLACE PAD ; : $OF ( -- ) POSTPONE OVER POSTPONE =$ POSTPONE IF POSTPONE DROP ; IMMEDIATE : ESCAPE-HANDLER ( caddr -- ) CASE " [5~" $OF ." PGUP " ENDOF " [6~" $OF ." PGDN " ENDOF " [A" $OF ." -LINE " ENDOF " [B" $OF ." +LINE " ENDOF " [D" $OF ." LEFT " ENDOF " [C" $OF ." RIGHT " ENDOF " [Z" $OF ." -TAB " ENDOF ENDCASE ; The screen shot shows this little test code running the code about. It exits with ^C . ( CHAR 03) HEX 1B CONSTANT [ESC] : TESTER BEGIN KEY DUP [ESC] = IF READSEQ ESCAPE-HANDLER ELSE DUP EMIT THEN 3 = UNTIL ;
  19. Just curious... Has anyone tried CAMEL99Forth /TTY version? I am also curious how it works with TIPI or some other disk drives on TI-99 systems.
  20. I was thinking the same thing. You could read/write the files in 4K chunks the way Rich is doing it. (i believe)
  21. Is it loading text files or program files? The 99 goes like blazes on program loading.
  22. I don't have any fancy drives on my TI-99 but even when I test loading files into SAMS memory on Classic99 it is pretty slow. From what I can see on your video you are loading about 1.4K bytes per second. On my SAMS editor on Classic99 I loaded a 13.6K file (the editor source) in about 7.5 seconds. That included erasing the 64K segment which took just over 1 second. So just a touch faster but of course Classic99 may well be serving up the files much faster than TIPI.
  23. Well... I had never tested my file util shell using APPEND mode and of course there was a bug. ? But you have been well looked after and I can now APPEND files to my hearts content. Thanks for forcing me to test better. I love the editor BTW.
×
×
  • Create New...