Jump to content
IGNORED

fbForth—TI Forth with File-based Block I/O [Post #1 UPDATED: 06/09/2023]


Lee Stewart

Recommended Posts

While adding speech and sound processing to the fbForth 2.0 ISR, I worried about the impact on program execution times. The fbForth 2.0 ISR, listed in the spoiler below, processes up to one speech list ISR, two sound list ISRs and one user ISR. If none of those four possible ISRs is active, the fbForth 2.0 ISR still processes minimal code every frame. That minimal code is highlighted in gold in the code in the spoiler:



* _____ ____ __ __ ___________

* / _/ / / __/__ ____/ /_/ / / _/ __/ _ \

* / _/ _ \/ _// _ \/ __/ __/ _ \ _/ /_\ \/ , _/

* /_//_.__/_/ \___/_/ \__/_//_/ /___/___/_/|_|

*

;[*** Interrupt Service =======================================================

* This routine is executed for every interrupt. It processes any pending

* speech. It then looks to see whether a user ISR is installed in ISR. If so,

* it sets up NEXT for execution of the user ISR. This will work only if the

* user has installed an ISR using the following steps in the following order:

*

* (1) Write an ISR with entry point, say MYISR.

* (2) Determine code field address of MYISR with this high-level Forth:

* ' MYISR CFA

* <<< Maybe need a word to do #3 >>>

* (3) Write CFA of MYISR into user variable ISR.

*

* Steps (2)-(3) in high-level Forth are shown below:

* ' MYISR CFA

* ISR !

*

* <<< Perhaps last step above should be by a word that disables interrupts >>>

*

* The console ISR branches to the contents of >83C4 because it is non-zero,

* with the address, INT1, of the fbForth ISR entry point below (also, the

* contents of INTLNK). This means that the console ISR will branch to INT1

* with BL *R12 from WP = GPLWS (>83E0), R12 containing INT1 below to first

* process any pending speech.

*

* If the user's ISR is properly installed, the code that processes the user

* ISR modifies NEXT so that the very next time B *NEXT or B *R15 is executed

* from Forth's workspace (MAINWS), the code at INT2 will process the user's

* ISR just before branching to the normal NEXT entry ($NEXT) in fbForth's

* inner interpreter.

*** ==========================================================================


* ¡¡¡ MUST REMEMBER THAT WE ARE IN GPL WORKSPACE UPON ENTRY. !!!


INT1 EQU $LO+$-LLVSPT

LI R0,BRSTK load address of top of Branch Address Stack

*

* Set up for pending speech

*

MOV @SPCSVC,*R0 save Speech service address onto Branch Stack

JEQ SNDCH1 jump to sound-check if no speech

INCT R0 increment Branch Stack

*

* Set up for pending sound list

*

SNDCH1 MOV @SND1ST,R1 sound list SL#1 to service?

JEQ SNDCH2 process speech and sound if needed

LI R1,PLAYL1 load PLAYL1 address and...

MOV R1,*R0+ ...push it onto Branch Stack


SNDCH2 MOV @SND2ST,R1 sound list SL#2 to service?

JEQ PRCSPS process speech and sound if needed

LI R1,PLAYL2 load PLAYL2 address and...

MOV R1,*R0+ ...push it onto Branch Stack


PRCSPS CI R0,BRSTK any speech or sound to process?

JEQ USRISR if not, jump to user ISR processing

LI R1,BNKRST yup..load return address

MOV R1,*R0 push return address onto Branch Stack

*

* Process pending speech and sound

*

MOV @MYBANK,@BANKSV save bank at interrupt

CLR @>6002 switch to bank 2 for speech & sound services

LI R7,BRSTK load top of Branch Stack

MOV *R7+,R8 pop speech/sound ISR

B *R8 service speech/sound

*

* Restore interrupted bank

*

BNKRST EQU $LO+$-LLVSPT return point for speech and sound ISRs

MOV @BANKSV,R0 restore bank at interrupt

SRL R0,13 get the bank# to correct position

AI R0,>6000 make it a real bank-switch address

CLR *R0 switch to the bank at interrupt

*

* Process User ISR if defined

*

USRISR MOV @$ISR+$UVAR,R0 User ISR installed?

JEQ INTEX

*

* Fix NEXT so that the user's ISR is processed the next time B *NEXT (B *R15)

* is executed from Forth's WS (MAINWS = >8300), which it does at the end of

* every CODE word, keyboard scan and one or two other places.

*

LI R1,INT2 Load entry point, INT2

MOV R1,@2*NEXT+MAINWS Copy it to Forth's NEXT (R15)

*

* The following 3 instructions are copies of the remainder of the console ROM's

* ISR (except that 'CLR R8' was removed because it is only needed by TI Basic)

* because we're not going back there!

*

INTEX LWPI >83C0 Change to console's ISR WS

RTWP Return to caller of console ISR

*

* Branch through above-modified NEXT (R15) gets us here. NEXT will be restored

* before executing user's ISR. INT3 (cleanup routine below) will be inserted

* in address list to get us back here for cleanup after user's ISR has finished.

* User's ISR is executed at the end of this section just before INT3.

*

INT2 EQU $LO+$-LLVSPT

LIMI 0 Disable interrupts

MOVB @>83D4,R0 Get copy of VR01

SRL R0,8 ...to LSB

ORI R0,>100 Set up for VR01

ANDI R0,>FFDF Clear VDP-interrupt-enable bit

BLWP @VWTR Turn off VDP interrupt

LI NEXT,$NEXT Restore NEXT

SETO @INTACT Set Forth "pending interrupt" flag

DECT R Set up return linkage by pushing

MOV IP,*R ...IP (R13, next Forth CFA) to return stack and

LI IP,INT3 ...setting IP to INT3 (below) for cleanup

MOV @$ISR(U),W Do the user's Forth ISR by executing

B @DOEXEC ...it through Forth's inner interpreter

*

* Clean up and re-enable interrupts.

*

INT3 EQU $LO+$-LLVSPT

DATA INT3+2 $NEXT (or $SEMIS) puts INT3+2 in W (R10)

DATA INT3+4 DOEXEC (or $SEMIS) will branch to *W = INT3+4 (next instr)

MOV *R+,IP Start cleanup: pop IP from before call to user's ISR

CLR @INTACT Clear Forth "pending interrupt" flag

MOVB @>83D4,R0 Prepare to restore VR01 by...

SRL R0,8 ...moving payload to LSB (enabling VDP interrupt) and

AI R0,>100 ...VR # (01) to MSB

MOVB @VDPSTA,R1 Remove pending VDP interrupt by reading VDP status

BLWP @VWTR Write VR01

LIMI 2 Re-enable interrupts

B *NEXT Continue normal task

;]*



If the impact of the above, minimal ISR processing is deemed excessive, the fbForth 2.0 ISR can be disabled by clearing the value at >83C4 (the console ISR hook):


HEX 0 83C4 !


and restoring it


HEX INTLNK @ 83C4 !


when it is necessary to process speech, sound and/or user ISRs.


In case you didn't know, the fbForth 2.0 ISR (derived from the TI Forth ISR) is designed to process ISRs written in high-level Forth. They just cannot expect or leave anything on the stack.


...lee

Link to comment
Share on other sites

Here are some sound lists for you to aid in testing the current beta (see post #1271 above):

 

 

 

( CHIME and CRASH are copied from the E/A Manual, pp. 321 – 4...)
HEX
: CHIME ( -- addr )
DATA[
059F BFDF FFE3 0109 8E01 A402 C501 90B6 D306 0391 B7D4 0503 92B8 D504
05A7 0493 B0D6 0503 94B1 D706 0395 B2D8 0705 CA02 96B3 D006 0397 B4D1
0503 98B5 D204 0585 0390 B6D3 0503 91B7 D406 0392 B8D5 0705 A402 93B0
D606 0394 B1D7 0503 95B2 D804 05C5 0196 B3D0 0503 97B4 D106 0398 B5D2
0703 9FBF DF00
]DATA DROP ;
: CRASH ( -- addr )
DATA[
039F E4F2 0502 E4F0 0C02 E4F2 0A02 E4F4 0802 E4F6 0602 E4F8 0402 E4FA
0201 FF00
]DATA DROP ;
DECIMAL
( AIRBURSTSND [similar to CRASH], GROUNDBURSTSND and INFLIGHTSND are )
( from Mark Wills {@Willsy}...)
HEX
: AIRBURSTSND ( -- addr )
DATA[
059F BFDF E5F2 0302 E5F0 0902 E5F2 0802 E5F4 0602 E5F6 0402 E5F8 0202
E5FA 0101 FF00
]DATA DROP ;
: GROUNDBURSTSND ( -- addr )
DATA[
079F BFC2 0EDF E3F0 0302 E5F0 1502 E3F2 0302 E5F2 1202 E3F4 0202 E5F4
1002 E3F6 0202 E5F6 0802 E3F8 0102 E5FA 0604 FFDF BF9F 0000
]DATA DROP ;
: INFLIGHTSND ( -- addr )
DATA[
05E4 F09F BFDF 1201 F110 01F3 0801 F507 01F8 0601 FC05 01FF 0000
]DATA DROP ;
DECIMAL

 

 

 

We will get a better test of the muting property of PLAY with a longer sound list. If anyone has one, please post it.

 

...lee

Link to comment
Share on other sites

OK...I just produced a much longer sound list by converting an XB program

 

1000 REM ****** JESU *******“

1010 REM * BACH,KEESEY,FOX *

...

 

that plays J. S. Bach's “Jesu, Joy of Man’s Desiring”. It is the only word defined in this blocks file: JESU.zip

 

You load and PLAY the JESU sound word with

 

USEBFL DSK1.JESU

1 LOAD

JESU 1 PLAY ( or 0 PLAY)

 

When I played the chime sound list from my last post in the muting mode while JESU was playing,

 

CHIME -1 PLAY

 

it became apparent that I need to change something in the mute part of the sound driver, PLYLST, because it only works properly for the first sound list of the second sound-list set ( CHIME )—I use “sound-list set” here because what I've been calling “sound lists” are actually lists of sound lists and that is what tripped me up.

 

Anyway, in the process of writing the routine to actually convert the XB SOUND statements contents to an fbForth 2.0 sound-list set, I discovered a more serious bug in fbForth 2.0, which I must run down before I go further. I was trying to BSAVE my system with the TMS9900 Assembler loaded, when it went off into the weeds (read, “branched to the wrong bank somewhere”). This was in Classic99 QI388. I suspect something in my extensive changes to save space and correct enabling interrupts in the wrong places. Has anyone tried BSAVE on real iron with the latest beta? I will try to get to it tonight. Right now I must do some (a lot of! :-o) yard work.

 

...lee

Edited by Lee Stewart
Link to comment
Share on other sites

... Anyway, in the process of writing the routine to actually convert the XB SOUND statements contents to an fbForth 2.0 sound-list set, I discovered a more serious bug in fbForth 2.0, which I must run down before I go further. I was trying to BSAVE my system with the TMS9900 Assembler loaded, when it went off into the weeds (read, “branched to the wrong bank somewhere”). This was in Classic99 QI388. I suspect something in my extensive changes to save space and correct enabling interrupts in the wrong places. Has anyone tried BSAVE on real iron with the latest beta? ...

 

...lee

 

This is embarrassing! :woozy: —the “more serious bug” was simply an incomplete handling of moving the BSAVE body from bank 1 to bank 2. I, indeed, moved the body code; but, I forgot to tell the code that branches to it to go to bank 2!?! :roll: It's all better, now! The attached beta shows as fbForth 2.0:=: fbForth2.0-BETA_20160526SAMS.zip

 

As soon as I fix the muting problem in PLAY , I will post fbForth 2.0:8.

 

...lee

Link to comment
Share on other sites

Hey Lee--it is beeter to have an ooops bug with a quick fix than to have a thorny-nasty one that takes weeks to get to the bottom of. I'm glad this one was of the former type. :) Note, you might want to double-check the other routines you moved around to make sure that the evil bug didn't strike there too. . .

Link to comment
Share on other sites

Hey Lee--it is better to have an ooops bug with a quick fix than to have a thorny-nasty one that takes weeks to get to the bottom of. I'm glad this one was of the former type. :) Note, you might want to double-check the other routines you moved around to make sure that the evil bug didn't strike there too. . .

 

Agreed. I have every intention of doing just such checking. I am pretty sure, though, that BSAVE was the only such move. Other moves were new code, so that's an unlikely mistake for them— COLD comes to mind. I converted COLD from high-level Forth in bank 0 to ALC in bank 2—branching to another bank for the first time for that word. The problem with BSAVE was that I just put the file containing its ALC in a different assembly spot (after bank 2's header) and forgot to tell its code field in bank 0—sort of like moving without leaving the post office a forwarding address.

 

I would very much like to get a test of SAMS capability on RI before I release the next binary (hint, hint); but, alas, I do not yet have a SAMS card. I must remedy that lack very soon! I also am down to my last black board and AM27C256 EPROM—we should get some Cincy Chili soon to exchange $$ and hdwe! :waving:

 

...lee

Link to comment
Share on other sites

Agreed on the need to meet up again soon, my friend. It is about time for another MANNERS meeting. . .now all we have to do is to get a few of the other DC local types to show up. ;)

 

I can make one of those SAMS cards magically appear in your hands too, as I'll be building a few more of them this weekend now that all of my parts are here. . .

  • Like 1
Link to comment
Share on other sites

I believe fbForth 2.0:8 is finally ready! :-o I have fixed the muting problem:

  • Changed one, left-over, explicit sound-chip write to go through the proper soundlist register (my invention);
  • Explicitly muted the noise and all three tone generators before starting second soundlist;
  • Unmuted the first soundlist when either duration byte or sound-bytes-to-load byte is 0 (I had forgotten the former)

I want to make one more visual scan of moved code as well as to test PLAY on real iron. I will probably release build 8 tonight. Here is the current beta for anyone who wants to run tests before that—especially, anyone with a SAMS card and a means of burning the fbForth cartridge (E)EPROM (probably only @Ksarul at this juncture). This beta shows as fbForth 2.0:<: fbForth2.0-BETA_20160527SAMS.zip

 

If you downloaded the JESU blocks file from post #1278 and copied the sound lists from the post before that, you can test the muting feature of PLAY as follows:

 

First, enter the sound lists, CHIME et al. Then, execute the following:

 

USEBFL DSK1.JESU

1 LOAD

JESU 1 PLAY

 

After letting JESU play for a few seconds, execute the following ( CHIME can be any, relatively short sound list):

 

CHIME -1 PLAY

 

CHIME should interrupt JESU with no sound from JESU . When CHIME is finished, JESU should resume as though never interrupted, i.e., JESU will not have been paused, just muted for the duration of CHIME .

 

...lee

  • Like 1
Link to comment
Share on other sites

On real iron, I get no behavior out of >MAP. and SAMS? reports 0

I have the 1 meg SAMS 2016 card in the system, it had passed the SAMTEST4.

 

My test:

 

HEX

EFA0 S0&TIB! . ( S0&TIB! leaves the new address on the stack )

S0 @ .

TIB @ .

FF F000 !

F000 @ . (expect to see FF)

0 F000 >MAP

0 F000 !

F000 @ . (expect to see 0)

FF F000 >MAP

F000 @ . (expect to see FF, but see 0)

SAMS? . (expect to see 1, but see 0, probably should have started with SAMS?)

 

-M@

Link to comment
Share on other sites

Calling S0&TIB! with a value that is too low kicked me out of HEX mode. It produced a new fbForth 2.0:< prompt. Is that too be expected?

 

Yes. You should have seen the error message, “S0 too low!” ahead of “fbForth 2.0:<”. After the error message, ABORT is called, which resets the stack to the current S0 , the error count ECOUNT to 0 and the radix to decimal; issues the “fbForth 2.0:<” message and calls QUIT , which resets the return stack to R0 (not register 0), resets interpreter input to the TIB and sets up the infinite loop that calls INTERPRET .

 

...lee

Link to comment
Share on other sites

On real iron, I get no behavior out of >MAP. and SAMS? reports 0

I have the 1 meg SAMS 2016 card in the system, it had passed the SAMTEST4.

 

My test:

 

HEX

EFA0 S0&TIB! . ( S0&TIB! leaves the new address on the stack )

S0 @ .

TIB @ .

FF F000 !

F000 @ . (expect to see FF)

0 F000 >MAP

0 F000 !

F000 @ . (expect to see 0)

FF F000 >MAP

F000 @ . (expect to see FF, but see 0)

SAMS? . (expect to see 1, but see 0, probably should have started with SAMS?)

 

-M@

 

It is, indeed, better to run SAMS? first; but, for testing purposes here, running >MAP to verify that the value SAMS? reports is actually correct is useful. SAMS? actually only reads a memory location in low RAM. The startup code first writes the flag to ARG (>835C) because the startup code used to copy a “DATA 0” statement to low RAM after that, which would, of course, trash the flag. The write to ARG survives in Classic99 until it is copied to the permanent, low-RAM location, but I can change that in case ARG is trashed before the re-copy because, now, the low-RAM location is only EQUated and should survive the startup code copy.

 

In the present case, however, it would appear that the SAMS card is, indeed, not properly interacting with fbForth because >MAP does not check the SAMS flag—it just tries to do the mapping.

 

Do you have a TurboForth cartridge you can check? >MAP should work exactly the same in TF as it does in fbF because I am using TF's code.

 

...lee

Link to comment
Share on other sites

OK...here's the TurboForth code for the body of >MAP :

;[ ; >MAP ( bank address -- )
; If a SAMS card is present, maps memory bank "bank" to address "address"
_sams  mov  r12,r11        ; save address of NEXT
       mov  *stack+,r1     ; get address
       andi r1,>f000       ; set to 4k boundary
       srl  r1,11          ; divide by 2048
       ai   r1,>4000       ; convert to SAMS register address
       mov  *stack+,r2     ; get bank
       andi r2,>ff         ; mask off any crap
       mov  r2,r0          ; keep a copy
       sla  r2,8           ; move to high byte
       xor  r0,r2          ; combine r0 & r2. Hi & lo bytes are now identical
       li   r12,>1e00      ; cru address of SAMS
       sbo  0              ; enable SAMS registers
       mov  r2,*r1         ; poke sams register
       sbz  0              ; disable sams registers
       mov  r11,r12        ; restore address of NEXT
       b    @retB0         ; return to caller
;]
 

and here is the equivalent fbForth code:

 

* If a SAMS card is present, >MAP maps memory bank "bank" to address "addr"
*
* DATA SOUN_N
* TOMP_N DATA 4+TERMBT*LSHFT8+'>','MA','P '+TERMBT
* TOMAP  DATA $+2
*        BL   @BLF2A
*        DATA _TOMAP->6000+BANK2

_TOMAP MOV  *SP+,R1        get address
       MOV  *SP+,R2        get bank
       ANDI R1,>F000       set to 4KiB boundary
       SRL  R1,11          divide by 2048
       AI   R1,>4000       convert to SAMS register address
       ANDI R2,>FF         mask off any crap
       MOV  R2,R0          keep a copy
       SLA  R2,8           move to high byte
       XOR  R0,R2          combine R0 & R2. MSB & LSB are now identical
       LI   CRU,>1E00      CRU address of SAMS
       SBO  0              enable SAMS registers
       MOV  R2,*R1         poke SAMS register
       SBZ  0              disable SAMS registers
       B    @RTNEXT        back to inner interpreter
;]
Though different registers, TF's stack is the same as fbF's SP. And, fbF's CRU is R12.

 

...lee

Link to comment
Share on other sites

The fbF code above is identical to the TF code. I do not understand how they can give different results. Let me know if there is other code you need to help make sense of this. I can certainly post the entire 4 banks of code. I actually plan to do that soon, anyway. Anybody else with both fbForth cartridge (with current beta) and a SAMS card?

 

...lee

Link to comment
Share on other sites

The fbF code above is identical to the TF code. I do not understand how they can give different results. Let me know if there is other code you need to help make sense of this. I can certainly post the entire 4 banks of code. I actually plan to do that soon, anyway. Anybody else with both fbForth cartridge (with current beta) and a SAMS card?

 

...lee

 

Keep in mind, that the code is working in the emulator. This makes me think it is an initialization difference. The page below has the assembly code that looks a lot like what you are using, but suggest that the mapping chip has some modes that must be controlled. passive or mapping mode, controlled by bit 1 of CRU 1E00. Neither of the turboforth or fbforth code actually enables the mapping mode. It just manipulates the mapping registers.

 

http://www.unige.ch/medecine/nouspikel/ti99/superams.htm#low-level

 

So, I'm guessing in TurboForth somewhere, when the SAMS is detected, the top pages are mapped into 32k space, and mapping mode is turned on? Is fbforth doing that?

 

I tried implementing the assembly on Thiery's page as fbForth assembly words, but I'm not skilled at that, and they didn't work either on hardware or emulation.

 

I tried:

 

HEX

ASM: MAPON ( -- )

1E00 R12 LI,

1 SBO,

;ASM

 

-M@

Link to comment
Share on other sites

 

Keep in mind, that the code is working in the emulator. This makes me think it is an initialization difference. The page below has the assembly code that looks a lot like what you are using, but suggest that the mapping chip has some modes that must be controlled. passive or mapping mode, controlled by bit 1 of CRU 1E00. Neither of the turboforth or fbforth code actually enables the mapping mode. It just manipulates the mapping registers.

 

http://www.unige.ch/medecine/nouspikel/ti99/superams.htm#low-level

 

So, I'm guessing in TurboForth somewhere, when the SAMS is detected, the top pages are mapped into 32k space, and mapping mode is turned on? Is fbforth doing that?

 

I tried implementing the assembly on Thiery's page as fbForth assembly words, but I'm not skilled at that, and they didn't work either on hardware or emulation.

 

I tried:

 

HEX

ASM: MAPON ( -- )

1E00 R12 LI,

1 SBO,

;ASM

 

-M@

 

I am mapping the upper banks to the 32KiB space just as TurboForth does; but that only happens if the SAMS card is detected. TF may be doing it whether or not it is detected. I will check that detail.

 

Regarding your fbForth assembly, source and destination operands are in the same order as in TMS9900 Assembler. It is only the operation that is at the end instead of the beginning. Your code should be

 

HEX

ASM: MAPON ( --- )

R12 1E00 LI,

1 SBO,

;ASM

 

...lee

Link to comment
Share on other sites

It does look like the mapping setup in TurboForth is performed assuming the SAMS card is present. If it is, the mapping-enabled action worked. If it is not, it had no effect. I will change that around in a bit and post another beta.

 

Before I do that, do you know whether it might be possible to detect the SAMS card's presence with the magic number, >AA, as with other DSRs? That would dramatically simplify this process.

 

...lee

Link to comment
Share on other sites

It does look like the mapping setup in TurboForth is performed assuming the SAMS card is present. If it is, the mapping-enabled action worked. If it is not, it had no effect. I will change that around in a bit and post another beta.

 

Before I do that, do you know whether it might be possible to detect the SAMS card's presence with the magic number, >AA, as with other DSRs? That would dramatically simplify this process.

 

...lee

There is no DSR on the board. CRU is used to pull the mapping chip into the DSR space as a memory mapped device, where each register can be written to.

 

-M@

Link to comment
Share on other sites

If this works, we need to track down what might be wrong with SAMS! because it is the same code that runs at startup to set up the SAMS card. I suppose it might be possible that a rearrangement of banks may take place that puts memory in an inconsistent state, in which case, perhaps, we should do away with SAMS! . I await your results with the last beta. :ponder:

 

...lee

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...