cas Posted October 31, 2007 Share Posted October 31, 2007 Hello, this is a new "Basic to Forth" course. I did something similar already last year in the ABBUC Forum, I'll start it here in english language. The course will present 2-3 little code snippets each week, explaining how it is done in BASIC and then how to do the same stuff in Forth, using VolksForth as an example. I'll start by publishing the issues I already did in the ABBUC Forum, and then I'll continue with new issue in both Forums (German version in the ABBUC Forum, English one here). The course is using Atari 8Bit specific features, so it is only partially portable to other platforms. Issue 1 - Sound This time we cover sounds. I have found the Basic Program below to which creates a hoover sound. 10 REM European hooter 15 LOW=57:HIGH=45:P=45 20 FOR AGAIN=1 TO 20 30 SOUND 0,P,10,14 40 FOR WAIT = 1 TO 180: NEXT WAIT 50 P=LOW:LOW=HIGH:HIGH=P 60 NEXT AGAIN 70 SOUND 0,0,0,0 80 END In VolksFORTH there is no build in SOUND command, so we have to build one that is compatible with the BASIC Sound command. \ Atari 8bit Sound Command $D200 CONSTANT AUDBASE : SOUND ( CH# FREQ DIST VOL -- ) SWAP $10 * + ROT DUP + AUDBASE + ROT OVER C! 1+ C!; With that new Word SOUND we can recreate the "hoover" sound in Forth. : hoover 57 54 ( Sound values for hoover sound ) 20 0 DO OVER 0 SWAP 10 14 SOUND 500 0 DO LOOP ( delay loop ) SWAP ( change sounds ) LOOP 0 0 0 0 SOUND; The BASIC Program uses 5 variables (LOW, HIGH, P, AGAIN, WAIT), the Forth version works without any variable declaration, all values are passed on the stack. This is one reason why Forth is memory efficient. Quote Link to comment Share on other sites More sharing options...
Gury Posted October 31, 2007 Share Posted October 31, 2007 That's fascinating. I look forward for future installments of VolksFORTH tutorial you will provide. It is so easier to learn it this way. Thank you! I think more people will start digging deeply in the secrets of this mystical language Quote Link to comment Share on other sites More sharing options...
+Larry Posted November 1, 2007 Share Posted November 1, 2007 That's fascinating. I look forward for future installments of VolksFORTH tutorial you will provide. It is so easier to learn it this way. Thank you! I think more people will start digging deeply in the secrets of this mystical language What did you understand from the Forth code presented? What does this line do? SWAP $10 * + ROT DUP + AUDBASE + ROT OVER C! 1+ C!; I gleaned that loops are inverted, as pretty much everything in Forth is in RPN. I certainly laud Carsten's efforts, but unless one already *knew* Forth, I really doubt that the above line means much of anything. -Larry Quote Link to comment Share on other sites More sharing options...
cas Posted November 1, 2007 Author Share Posted November 1, 2007 That's fascinating. I look forward for future installments of VolksFORTH tutorial you will provide. It is so easier to learn it this way. Thank you! I think more people will start digging deeply in the secrets of this mystical language What did you understand from the Forth code presented? What does this line do? SWAP $10 * + ROT DUP + AUDBASE + ROT OVER C! 1+ C!; I gleaned that loops are inverted, as pretty much everything in Forth is in RPN. I certainly laud Carsten's efforts, but unless one already *knew* Forth, I really doubt that the above line means much of anything. -Larry Hello Larry, I agree. The Sound Word needs some explanation. It builds the same command as is available in Basic. THe content of this word in detail CH# = Pokey Sound Channel 0-3 FREQ - Frequency DIST - distortion VAL - Sound volume The comment show what is on the Stack : SOUND ( CH# FREQ DIST VOL -- ) SWAP ( CH# FREQ VOL DIST -- we swap volume and distortion ) $10 ( CH# FREQ VOL DIST $10 -- hexadecimal $10 or decimal 16 on the stack ) * ( CH# FREQ VOL DIST*$10 -- distortion is now multiplied by 16 ) + ( CH# FREQ VOL+DIST*$10 -- volume and distortion are added together ) ROT ( FREQ VOL+DIST*$10 CH# -- we rotate the topmost 3 stack items, brining CH# on the top ) DUP ( FREQ VOL+DIST*$10 CH# CH# -- we duplicate the topmost stack item, the Channel ) + ( FREQ VOL+DIST*$10 CH#+CH# -- the Pokey Frequency Registers are two bytes apart, so we multiply the channel by 2 by adding the channel values ) AUDBASE ( FREQ VOL+DIST*$10 CH#*2 $D200 -- we put the constant AUDBASE on the Stack, value is $D200, the first pokey frequency register ) + ( FREQ VOL+DIST*$10 CH#*2+$D200 -- we add the channel to AUDBASE ) ROT ( VOL+DIST*$10 CH#*2+$D200 FREQ -- we rotate the topmost 3 Stackitems, bringing the Frequency on top ) OVER ( VOL+DIST*$20 CH#*2+$D200 FREQ CH#*2+$D200 -- OVER copies the 2nd Stackitem on the Top of the Stack ) C! ( VOL+DIST*$20 CH#*2+$D200 -- we store [think POKE] the Frequency value in the Pokey Frequency register ) 1+ ( VOL+DIST*$20 CH#*2+$D200+1 -- we increment the topmosat stackvalue, which points now on the register for volume and distortion ) C! ( -- we store volume and distortion in the Pokeys volume and distortion register ) ; ( end of definition of SOUND word ) And now the same stuff with real values for the command 0 54 10 14 SOUND : SOUND ( 0 54 10 14 -- ) SWAP ( 0 54 14 10 -- we swap volume and distortion ) $10 ( 0 54 14 10 16 -- hexadecimal $10 or decimal 16 on the stack ) * ( 0 54 14 160 -- distortion is now multiplied by 16 ) + ( 0 54 174 -- volume and distortion are added together ) ROT ( 54 174 0 -- we rotate the topmost 3 stack items, brining CH# on the top ) DUP ( 54 174 0 0 -- we duplicate the topmost stack item, the Channel ) + ( 54 174 0 -- the Pokey Frequency Registers are two bytes apart, so we multiply the channel by 2 by adding the channel values ) AUDBASE ( 54 174 0 $D200 -- we put the constant AUDBASE on the Stack, value is $D200, the first pokey frequency register ) + ( 54 174 $D200 -- we add the channel to AUDBASE ) ROT ( 174 $D200 54 -- we rotate the topmost 3 Stackitems, bringing the Frequency on top ) OVER ( 174 $D200 54 $D200 -- OVER copies the 2nd Stackitem on the Top of the Stack ) C! ( 174 $D200 -- we store [think POKE] the Frequency value 64 in the Pokey Frequency register $D200 ) 1+ ( 174 $D201 -- we increment the topmosat stackvalue, which points now on the register for volume and distortion ) C! ( -- we store volume and distortion 174 in the Pokeys volume and distortion register $D201 ) ; ( end of definition of SOUND word ) Quote Link to comment Share on other sites More sharing options...
+Larry Posted November 1, 2007 Share Posted November 1, 2007 Hi Carsten- Thanks for the additional documentation -- it is very helpful. -Larry Quote Link to comment Share on other sites More sharing options...
Shawn Jefferson Posted November 2, 2007 Share Posted November 2, 2007 I didn't have a clue what the Forth code was doing either. Whoever invented RPN needed more friends as a kid, but I guess I understand why he didn't have that many. Quote Link to comment Share on other sites More sharing options...
cas Posted November 2, 2007 Author Share Posted November 2, 2007 I didn't have a clue what the Forth code was doing either. Whoever invented RPN needed more friends as a kid, but I guess I understand why he didn't have that many. It takes some time to start Thinking in Forth, but then programming is more pleasure (even in other languages like Java, Assembler or C), as programs become more modular, compact and reusable. People who learn Forth as their first programming language (I know a teacher who does Forth programming of robots in undergraduate school) find Forth and RPN quite natural. Only people that have adapted their brains to Algol type languages find it difficult (It took me 2-3 years, but it was worth it). Same effect applies to LISP. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
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.