Jump to content

Photo

Camel99 Forth Information goes here

Camel99 Forth Concatentive Programming ANS Forth

284 replies to this topic

#276 TheBF OFFLINE  

TheBF

    Dragonstomper

  • Topic Starter
  • 963 posts
  • Location:The Great White North

Posted Fri Feb 22, 2019 11:03 AM

About that ISR driven RS232

 

I have got something pretty stable working for ISR on RS232/1 thanks again to all the help one gets here on Atariage.

The spoiler shows the current code and test routine and the little movie shows it in action at 9600 bps.

 

It is worth noting that at 9600 bps, sending a  7K file with a 256 byte buffer, the file was captured and echoed back to the terminal no problem.

The same test done a 19.2Kbps dropped characters near the end of the file.  So with a bigger buffer I can capture faster, but if I need the memory I need to slow down the sending a bit.

Or I could stop the echo and just put the bytes in storage buffer somewhere. However 9600 is fast enough for what I am doing.

 

Also note I am using expansion RAM (variables) for QHEAD and QTAIL not scratchpad RAM.  Seems to be ok for my needs.

 

For the assembly language coders out there, you can compare how I took insanemultitasker's code but gave the various routines names in the Forth "dictionary".

This means I can run the ALC routines from the Forth command line and see how the work.

Spoiler

Attached Files


Edited by TheBF, Fri Feb 22, 2019 11:09 AM.


#277 TheBF OFFLINE  

TheBF

    Dragonstomper

  • Topic Starter
  • 963 posts
  • Location:The Great White North

Posted Tue Feb 26, 2019 6:25 PM

Here a bug, there a bug, everywhere a bug bug. Old theBF had some RAM, ee I ee I oh!

 

I thought I was so clever using scratchpad memory after the >8300 workspace to hold Forth's USER VARIABLEs.  LOL 

The old machine got me again.  I can use the addresses up to 8344 for various system variables.

I tried placing I/O  vectors in the space after that and the !$@#%^ file sys DSR uses some of those locations.  :mad:

 

I have found that >8352 and >836E are un-touched (so far)  so I use those for vectors.

      20 USER: TFLAG             \ TASK flag awake/asleep status
      22 USER: JOB               \ Forth word that runs in a task
      24 USER: DP                \ dictionary pointer
      26 USER: HP                \ hold pointer, for text->number conversion
      28 USER: CSP
      2A USER: BASE
      2C USER: >IN
      2E USER: C/L               \ Chars per line (32 or 40 depending on VDP mode)
      30 USER: OUT               \ counts chars since last CR (newline)
      32 USER: VROW              \ current VDP column (in fast RAM)
      34 USER: VCOL              \ current VDP row (in fast RAM)
\     36 USER: CURRENT
\     38 USER: CONTEXT
      3A USER: LP                \ LEAVE stack pointer.
      3C USER: SOURCE-ID         \ 0 for console,  -1 for EVALUATE, 1 for include
      3E USER: 'SOURCE           \ WATCH OUT! This is 2variable, occupies 3E and 40
\      40 USER: -------          \ used by 'SOURCE
      42 USER: TPAD
\ *********************************************************************
       44 USER: 'KEY?           \ vector to test for key press
\       46 USER: ???     might be ok
\      48 USER: ---             \ DSR use *PROTECTED IN ROOT TASK
\      4A USER: ---             \ DSR use *PROTECTED IN ROOT TASK
\      4C USER: ---             \ DSR use *PROTECTED IN ROOT TASK
\      4E USER: ---             \ DSR use *PROTECTED IN ROOT TASK
\      50 USER: ---             \ DSR use *PROTECTED IN ROOT TASK
       52 USER: 'EMIT           \ vector for char. output routine
\      54 USER: ---  1+ DSRSIZ  \ DSR use *PROTECTED IN ROOT TASK
\      56 USER: ---  DSRNAM     \ DSR use *PROTECTED IN ROOT TASK
\      58 USER: ---             \ DSR use *PROTECTED IN ROOT TASK
       6E USER: 'PAGE           \ vector for screen clear routine



#278 TheBF OFFLINE  

TheBF

    Dragonstomper

  • Topic Starter
  • 963 posts
  • Location:The Great White North

Posted Tue Feb 26, 2019 6:37 PM

STRAIGHT     An old PolyForth word

After fighting with the ISR routine and getting it to work, I found I was not happy with how the rest of the system worked using the work around.

Polled I/O works great for keyboard entry so I wondered if there was a way to blast code at the machine when I needed to without fooling around with the GPL and ISR workspaces.

 

Someone here reminded me to disable interrupts for full attention of my polled code and sure enough that worked.

So I create STRAIGHT, a word from PolyForth and now I can blast source code into a big buffer in low RAM whenever I need to at full speed.

 

I had trouble getting the ALC code to wait for the first character so I just gave up and put that in Forth as well as the user notification stuff cuz that's way simpler in Forth.

 

Now I just need to write a little routine to write the buffer to a DV80 file and one to from memory and I have what I wanted. 

PC -> Ti-99 saving and/or compilation without leaving the terminal emulator.

\ STRAIGHT a word from PolyForth
\ Accept chars into a buffer with no echo
\ capable of reading continuous data at 9600 bps

NEEDS MOV, FROM DSK1.ASM9900

CREATE ALLDONE     \ branch here to exit readcom
         R12 RPOP,
         2 LIMI,
         R1 TOS MOV,  \ get the char count to Forth TOS
         NEXT,
DECIMAL
CODE READCOM ( addr n -- n' )
         R12 RPUSH,
         PORT @@ R12 MOV,       \ select the 9902
        *SP+ W MOV,             \ addr ->W   (ie: R8)
         W TOS ADD,             \ calc last address ->TOS
         R0 SETO,               \ set timeout register >FFFF
         R1 CLR,                \ reset char counter
         0 LIMI,                \ we need the entire machine
         BEGIN,
            21 TB,
            EQ IF,
               *W+ 8 STCR,    \ put char in buf & inc
                18 SBO,       \ clr rcv buffer
                R0 SETO,      \ reset timeout
                R1 INC,       \ count char
            ELSE,
                 R0 DEC,      \ no char, dec TIMEDOUT
                 EQ IF,
                    ALLDONE @@ B,
                 ENDIF,
            ENDIF,
            W TOS CMP,        \ W =   end of buffer ?
        EQ UNTIL,
        ALLDONE @@ B,
        ENDCODE

: STRAIGHT   ( addr len -- n)
       SWAP 1+ TUCK 1-   ( addr+1 n addr)
       CR ." Send file now..."
       KEY SWAP C!     \ store first Char
       READCOM
       CR ." Complete"  CKEY? DROP 
       CR ;

HEX


#279 TheBF OFFLINE  

TheBF

    Dragonstomper

  • Topic Starter
  • 963 posts
  • Location:The Great White North

Posted Wed Feb 27, 2019 9:26 PM

Xon/Xoff in Forth

 

I thought it would be handy to include a way to control the TI-99 sending data to the terminal. I remember using control S and control Q on the DEC 10 Terminal in the old days.

It means that any utility you write that is gushing data to the terminal can be stopped and started with the same key strokes. Handy.

 

By changing the routine that is plugged into the output vector 'EMIT, we get Xon/Off in Camel Forth.

 

In the process I discovered that making a  simple one byte buffer for a serial port receive routine has a benefit.

I only update the buffer if a new key was pressed.  It means the (XEMIT) routine does not have to run any CRU code to read the flow control key. 

 

Edit:  The reason this can work is because I read the keyboard in the utilities for a "break" by the user, therefore KBUFF gets filled with key while DUMP, or DIR etc. are running.

\ this is cross-compiler Forth

VARIABLE: KBUFF           \ holds the last char rcv'd

[CC] DECIMAL
CROSS-ASSEMBLING
CODE: CKEY? ( -- n )         \  "com-key"
         0 LIMI,
         R12 RPUSH,
         PORT @@ R12 MOV,    \ select >1340 CRU address
         TOS PUSH,
         TOS CLR,
         21 TB,              \ test if char ready
         EQ IF,
             TOS 8 STCR,        \ read the char
             18 SBZ,            \ reset 9902 rcv buffer
             TOS 8 SRL,         \ shift to other byte
             TOS KBUFF @@ MOV,  \ record the key press
         ENDIF,
         R12 RPOP,
         2 LIMI,
         NEXT,
         END-CODE

Xon Xoff in Forth

I recant: reading the byte buffer did not really give much advantage. Code changed.

\ XONXOFF.FTH
HEX
11 CONSTANT ^Q
13 CONSTANT ^S

: (XEMIT)  ( c -- )   \ * XON/XOFF version*
         KEY? ^S =
         IF
           BEGIN
              PAUSE    \ let another task have a turn while we wait
              KEY? DUP 3 = ABORT" ^C"
              ^Q =
           UNTIL
         THEN
         CEMIT ;   \ send c to comm TTY1

: XON/XOFF   ( -- ) ['] (XEMIT)  'EMIT ! ;
: NOHANDSHK  ( -- ) ['] (EMIT)   'EMIT ! ;

Edited by TheBF, Thu Feb 28, 2019 10:44 AM.


#280 TheBF OFFLINE  

TheBF

    Dragonstomper

  • Topic Starter
  • 963 posts
  • Location:The Great White North

Posted Sun Mar 3, 2019 8:33 PM

Making a Sound Lexicon for the TMS9919

 

Many years ago I remember wondering how I might tackle the challenge of programming the TMS9919 with a set of Forth words.

I spent some time today working on how it might be done and I modified my preliminary work.

 

This version lets you do the minus number duration trick that we have in TI- BASIC by running a very small ISR that just keeps trying to turn off the sound channels if the volume number is not zero.

 

The other thing I always wanted was  a  way to play BASS notes by frequency in Herz, so this word set has the word ( dur freq vol ) BASS which makes it easy.

Using the same math we can also play white noise notes that track frequency.  No kidding!

 

Here's the code.  I will have to make some demo recordings.  At the moment I have been using Vorticon's Stratego game sounds for inspiration.

 

EDIT: Created the word PLAY to save memory and improve code clarity

 

Spoiler

Edited by TheBF, Mon Mar 4, 2019 6:22 PM.


#281 TheBF OFFLINE  

TheBF

    Dragonstomper

  • Topic Starter
  • 963 posts
  • Location:The Great White North

Posted Tue Mar 19, 2019 6:30 AM

Semantic Power of the 9900 Instruction Set (Fantastic!)

 

While doing some analysis of how improve compiling times I zoomed in on a word in Camel Forth called DIGIT?.  This word takes an ascii character and converts it to a numeric value. It returns two arguments.

If the conversion is good the number and a true flag is left on the data stack. If the conversion is bad, the input character and a false flag are left on the data stack.

Camel Forth defines this function in Forth using some clever binary logic. 

 

However this word is called in a loop to convert multi-digit numbers so it was a good target to improve the speed of number interpretation and compilation.

 

Camel Forth's DIGIT? (original comments by Dr. Brad Rodriguez)

: DIGIT?     ( char -- n -1)             \ if char is a valid digit
\            (      -- x  0 )            \ if char is not valid
              DUP 39 > 100 AND +         \ silly looking
              DUP 140 > 107 AND -
              [CHAR] 0 -                 \ but it works!
              DUP BASE @ U< ;       

I used the GForth decompiler to see how it was done in GForth, one of the reference implementations of ANS/ISO Forth and I saw this:

: DIGIT?
      30 - 
      DUP 9 U>
      IF 7 - DUP 9 U<=
        IF
          DROP FALSE EXIT
        THEN
      THEN
      DUP BASE @ U>=
      IF
        DROP FALSE EXIT
      THEN
      TRUE ;

Looking at this example I wrote the equivalent in Forth assembler and it's almost a direct translation.  It actually worked the first time I coded it. ;-)

The 9900 instruction set is almost the same level as Forth, when structured branching and looping are added to the assembler.

 

*Notes:

  1. The combination of a jump token and IF,  ( GT IF,)  in this assembler simply create a JMP instruction around the following code to the nearest ENDIF, location.
  2. TOS is an alias for R4, used a cache register for the top value on the Forth data stack
  3. PUSH is a 2 instruction macro that decrements R6 and then moves R4 to the data stack  ( DECT R6    MOV R4,*R6 )

          

The code below puts the equivalent Forth code in the comments

CODE DIGIT? ( char -- n f )           \ : digit?
               TOS PUSH,              \ 2 extra instructions
               TOS -30 AI,            \ 30 -
               TOS 9 CI, GT           \ DUP 9 U>
               IF,                    \ IF
                  TOS -7 AI, LTE      \    7 - DUP 9 U<=
                  IF,                 \    IF
                      TOS CLR,        \       DROP FALSE
                      NEXT,           \       EXIT
                  ENDIF,              \    THEN
               ENDIF,                 \ THEN
               TOS BASE @@ CMP, GTE   \ DUP BASE @ U>=
               IF,                    \ IF
                  TOS CLR,            \     DROP FALSE
                  NEXT,               \     EXIT
               ENDIF,                 \ THEN
               TOS *SP MOV,           \ extra instruction
               TOS SETO,              \ TRUE
               NEXT,                  \ ;
               ENDCODE

Amazing design by TI Engineers all those years ago.

 

 



#282 Lee Stewart OFFLINE  

Lee Stewart

    River Patroller

  • 3,947 posts
  • Location:Silver Run, Maryland

Posted Tue Mar 19, 2019 9:12 AM

FYI, here is the ALC from TI Forth’s DIGIT (from fig-Forth) and the equivalent (I think!) fbForth Assembler code, which only leaves FALSE if the ASCII character cannot be converted to a digit:

Spoiler

 

...lee



#283 TheBF OFFLINE  

TheBF

    Dragonstomper

  • Topic Starter
  • 963 posts
  • Location:The Great White North

Posted Tue Mar 19, 2019 10:11 AM

FYI, here is the ALC from TI Forth’s DIGIT (from fig-Forth) and the equivalent (I think!) fbForth Assembler code, which only leaves FALSE if the ASCII character cannot be converted to a digit:

Spoiler

 

...lee

 

Ah... so the TI guys built this into TI-Forth in the '80s.   Makes sense.

 

The hi-level Forth version Brad did was 48 bytes, the code version based in GForth is 24 bytes and it is approximately 7X faster.  :)

 

All this points to the fact that modern commercial Forth systems have abandoned threaded code for native code. However it is a much harder compiler to build.



#284 Lee Stewart OFFLINE  

Lee Stewart

    River Patroller

  • 3,947 posts
  • Location:Silver Run, Maryland

Posted Tue Mar 19, 2019 10:56 AM

...

Camel Forth's DIGIT? (original comments by Dr. Brad Rodriguez)

: DIGIT?     ( char -- n -1)             \ if char is a valid digit
\            (      -- x  0 )            \ if char is not valid
              DUP 39 > 100 AND +         \ silly looking
              DUP 140 > 107 AND -
              [CHAR] 0 -                 \ but it works!
              DUP BASE @ U< ;       

 

Clever code, indeed—but it confused me at first because of a missing HEX ahead of the definition.  I especially like how the ASCII gap is handled.  It insures that any character in the gap is treated as a number higher than any likely radix (314 – 320), which should fail the comparison at the end of the definition.

 

[Edit:  I should add that the two AND operations will not work in TI Forth or fbForth because operations that yield TRUE or FALSE, unfortunately, render TRUE as 1 rather than -1 (FFFFh) as in the above case.]

 

...lee



#285 TheBF OFFLINE  

TheBF

    Dragonstomper

  • Topic Starter
  • 963 posts
  • Location:The Great White North

Posted Sat Mar 23, 2019 9:56 AM

CAMEL99 Forth Version G Release

 

I forgot how many things I had been working on since last November.  It's good to look back and see how far we've come sometimes.

I just posted version G. It fixes a bug in the interpreter error detection and adds a bunch of new library files.

 

https://github.com/bfox9900/CAMEL99-V2(forgot the link)

 

### Nov 30, 2018 V2.1.G

  • Version G corrects a long-time bug in the interpreter that reported
    "empty stack" under some conditions erroneously (CAMELG2.HSF)
  • Compiler switch name has been changed to USEFORTH (previously SMALLER) because
    sometimes Forth is smaller and sometimes Assembler code is smaller.
  • Version G has a code word for DIGIT? to improved compile times
  • The word ?SIGN is now PRIVATE, not visible in the dictionary to save space
  • The word >NUMBER has been changed slighly from the original CAMEL FORTH that speeds it for the 9900 cpu.
  • The ELAPSE.FTH program has been significantly improved for accuracy and the code size has been reduced.
  • A file based BLOCK system is available as a library: /LIB.ITC/BLOCKS.FTH
  • These blocks are compatible with FBFORTH and Turbo Forth allowing the developer read programs from these other Forth systems. 
    Compiling this code will not be possible without writing a "translation harness" however for simple programs this is not too difficult.
  • A simple demo of BLOCK usage is file LINEDIT80.FTH for use with 80col displays or the TTY based kernel CAMEL99T
  • Data structures per Forth 2012 are now supported in file STRUC12.FTH.
    A simple example is part of the file. (remove or comment out if you use the file)
  • ACCEPT has been changed passing backspace cursor control to EMIT. (see below)
  • EMIT has been changed to handle newline and backspace characters
  • (EMIT) and (CR) i/o primitives can be compiled as Forth or CODE (controlled by USEFORTH )
### CAMEL99T (tty)
  • Version CAMEL99T is built to use RS232/1 as the primary console.
    It has been tested with Tera Term, Hyper-terminal and PUTTY under windows 10.
    Terminal configuration is 9600,8,n,1, hardware handshake.
  • A word VTYPE ( $addr len VDPaddr -- ) is part of the CAMEL99T to allow simple printing to the VDP screen at a screen address. (no protection!)
  • Library file call XONXOFF.FTH vectors EMIT to provide XON/XOFF protocol.
  • File VT100.FTH can be included to provide cursor control for a VT100 terminal.

Edited by TheBF, Sat Mar 23, 2019 11:54 AM.






Also tagged with one or more of these keywords: Camel99, Forth, Concatentive Programming, ANS Forth

0 user(s) are browsing this forum

0 members, 0 guests, 0 anonymous users