Forth Meets AY-3-8912 and Plays Music

Topics relating to various Forth models on the 6502, 65816, and related microprocessors and microcontrollers.
Post Reply
Martin_H
Posts: 837
Joined: 08 Jan 2014

Forth Meets AY-3-8912 and Plays Music

Post by Martin_H »

I tried using BASIC, but quickly found myself hitting the limits of the language. But Forth came to the rescue, so here's a video of my SBC playing music using the AY-3-8912 card:

https://youtu.be/XmreeAXaim8

Code for anyone who wants to take a look:

Code: Select all

\ Define AY-3-8912 constants

\ The output frequency is equal to the clock frequency divided by 16 and then
\ divided by the number written to the course and fine pitch registers. So we
\ can use algebra to figure out the register value for a specific pitch.
\ Freq = 1,000,000 / 16 / Reg
\ Freq = 62500 / Reg
\ Reg = 62500 / Freq
\ Example Reg = 62500 / 440(A) = 142
3823 CONSTANT C_0
3406 CONSTANT D_0
3034 CONSTANT E_0
2863 CONSTANT F_0
2551 CONSTANT G_0
2273 CONSTANT A_0
2025 CONSTANT B_0
1911 CONSTANT C_1
1703 CONSTANT D_1
1517 CONSTANT E_1
1432 CONSTANT F_1
1278 CONSTANT G_1
1136 CONSTANT A_1
1012 CONSTANT B_1
956 CONSTANT C_2
851 CONSTANT D_2
758 CONSTANT E_2
716 CONSTANT F_2
638 CONSTANT G_2
568 CONSTANT A_2
506 CONSTANT B_2
478 CONSTANT C_3
426 CONSTANT D_3
379 CONSTANT E_3
358 CONSTANT F_3
319 CONSTANT G_3
284 CONSTANT A_3
253 CONSTANT B_3
239 CONSTANT C_4
213 CONSTANT D_4
190 CONSTANT E_4
179 CONSTANT F_4
159 CONSTANT G_4
142 CONSTANT A_4
127 CONSTANT B_4
119 CONSTANT C_5
107 CONSTANT D_5
95  CONSTANT E_5
90  CONSTANT F_5
80  CONSTANT G_5
71  CONSTANT A_5
64  CONSTANT B_5
59  CONSTANT C_6

HEX
7F00 CONSTANT WRITE
7F01 CONSTANT LATCH
0 CONSTANT AFREQ
2 CONSTANT BFREQ
4 CONSTANT CFREQ
6 CONSTANT NOISE
7 CONSTANT MIXER
8 CONSTANT VA
9 CONSTANT VB
A CONSTANT VC
B CONSTANT FL
C CONSTANT FH
D CONSTANT ES
E CONSTANT IA
F CONSTANT IB

\ Stores the stack value into VA
: VA!
  VA LATCH C!
  WRITE C! ;

\ Stores the stack value into VB
: VB!
  VB LATCH C!
  WRITE C! ;

\ Stores the stack value into VB
: VC!
  VC LATCH C!
  WRITE C! ;

: MIXER!
  MIXER LATCH C!
  WRITE C! ;

\ Deposits (value register) from stack to AY-3-8912
: REG!
  2DUP
  LATCH C!
  FF AND
  WRITE C!
  1+
  LATCH C!
  8 RSHIFT
  WRITE C! ;

\ holds a note
: DELAY
  950 0 DO
  LOOP ;

DECIMAL

\ Now use these functions to produce sound

: ARPEGGIO_UP
  A_4 AFREQ REG!
  DELAY
  C_5 AFREQ REG!
  DELAY
  E_5 AFREQ REG!
  DELAY
  G_5 AFREQ REG!
  DELAY ;

: ARPEGGIO_DOWN
  A_5 AFREQ REG!
  DELAY
  G_5 AFREQ REG!
  DELAY
  E_5 AFREQ REG!
  DELAY
  C_5 AFREQ REG!
  DELAY ;

: MEASURE1
  \ Start with the pedal tones
  B_3 BFREQ REG!
  E_3 CFREQ REG!
  2 VB!
  2 VC!

  \ Play the arpeggios sliently to count time.
  0 VA!
  ARPEGGIO_UP
  ARPEGGIO_DOWN
  ARPEGGIO_UP
  ARPEGGIO_DOWN ;

: MEASURE2
  \ Now turn off the pedal tones and play the arpeggios twice aloud.
  0 VB!
  0 VC!
  2 VA!
  ARPEGGIO_UP
  ARPEGGIO_DOWN
  ARPEGGIO_UP
  ARPEGGIO_DOWN ;

: MEASURE3
  \ Start with the pedal tones
  E_2 BFREQ REG!
  E_1 CFREQ REG!
  2 VB!
  2 VC!

  2 VA!
  ARPEGGIO_UP
  ARPEGGIO_DOWN
  ARPEGGIO_UP
  ARPEGGIO_DOWN ;

: MEASURE4
  E_2 BFREQ REG!
  B_2 CFREQ REG!
  2 VB!
  2 VC!

  ARPEGGIO_UP
  G_4 BFREQ REG!

  ARPEGGIO_DOWN
  ARPEGGIO_UP
  ARPEGGIO_DOWN ;

: MEASURE5
  0 VB!
  0 VC!

  ARPEGGIO_UP
  ARPEGGIO_DOWN
  ARPEGGIO_UP

  D_2 BFREQ REG!
  2 VB!
  ARPEGGIO_DOWN ;

: MEASURE6
  0 VB!
  0 VC!

  ARPEGGIO_UP
  ARPEGGIO_DOWN

  D_2 BFREQ REG!
  2 VB!

  A_4 AFREQ REG!
  DELAY
  C_5 AFREQ REG!
  DELAY
  E_5 AFREQ REG!
  DELAY
  B_2 BFREQ REG!
  G_5 AFREQ REG!
  DELAY

  0 VB!

  A_5 AFREQ REG!
  DELAY
  G_5 AFREQ REG!
  DELAY
  E_5 AFREQ REG!
  DELAY
  2 VB!
  C_5 AFREQ REG!
  DELAY ;

: MEASURE7
  D_2 BFREQ REG!
  2 VB!
  0 VC!
  2 VA!

  ARPEGGIO_UP
  ARPEGGIO_DOWN
  ARPEGGIO_UP
  ARPEGGIO_DOWN ;

: MEASURE8
  G_3 BFREQ REG!
  B_2 CFREQ REG!
  2 VB!
  2 VC!
  2 VA!

  ARPEGGIO_UP
  ARPEGGIO_DOWN
  ARPEGGIO_UP
  ARPEGGIO_DOWN ;

: MEASURE9
  B_2 BFREQ REG!
  G_2 CFREQ REG!
  2 VB!
  2 VC!
  2 VA!

  ARPEGGIO_UP

  G_3 BFREQ REG!
  D_3 CFREQ REG!

  ARPEGGIO_DOWN
  ARPEGGIO_UP
  ARPEGGIO_DOWN ;

: MEASURE10
  G_3 BFREQ REG!
  D_3 CFREQ REG!
  2 VB!
  2 VC!
  2 VA!

  ARPEGGIO_UP
  ARPEGGIO_DOWN

  F_3 BFREQ REG!
  0 VC!
  ARPEGGIO_UP

  D_3 BFREQ REG!

  ARPEGGIO_DOWN ;

: MEASURE11
  C_4 AFREQ REG!
  C_3 BFREQ REG!
  D_3 CFREQ REG!
  2 VB!
  2 VC!
  2 VA!
  DELAY
  DELAY
  DELAY
  DELAY
  DELAY
  DELAY
  DELAY
  DELAY
  1 VB!
  1 VC!
  1 VA!
  DELAY
  DELAY
  DELAY
  DELAY
  DELAY
  DELAY
  DELAY
  DELAY ;

: MEASURE12
  2 VA!
  0 VB!
  0 VC!

  C_4 AFREQ REG!
  DELAY

  E_4 AFREQ REG!
  DELAY

  G_4 AFREQ REG!
  DELAY

  A_4 AFREQ REG!
  DELAY

  G_4 AFREQ REG!
  DELAY

  E_4 AFREQ REG!
  DELAY

  C_4 AFREQ REG!
  DELAY
  DELAY

  DELAY
  DELAY
  DELAY
  DELAY
  DELAY
  DELAY
  DELAY
  DELAY ;

: SONG
  \ Set up the volume and mixer.
  248 MIXER!

  MEASURE1
  MEASURE2
  MEASURE2
  MEASURE3
  MEASURE2
  MEASURE4
  MEASURE5
  MEASURE3
  MEASURE5
  MEASURE3
  MEASURE6
  MEASURE7
  MEASURE2
  MEASURE8
  MEASURE9
  MEASURE10
  MEASURE11
  MEASURE12

  0 VB!
  0 VC!
  0 VA! ;
dwight
Posts: 213
Joined: 08 Jun 2004

Re: Forth Meets AY-3-8912 and Plays Music

Post by dwight »

A little wordy but looks to work.
You might look at how <builds ( or create ) does> could
be used to make a family of note words.
Also, don't be afraid to use more of the width of the paper.
A measure should be wide not tall.
It doesn't have to look like assembly code. In Forth you make
sentences that say something more than a single function on a line.
I hope you don't mind my comments.
Dwight
Martin_H
Posts: 837
Joined: 08 Jan 2014

Re: Forth Meets AY-3-8912 and Plays Music

Post by Martin_H »

I don't mind the feedback. My Forth chops aren't good enough to handle too much code on a single line. So I have to break it down into chunks I can understand.

I think the weakest part of the program is the delay generation and the use of a timing loop. It would probably be better to have constants for standard note values and have the program translate that into a delay, rather than sprinkle delay calls all around the program.
User avatar
Dr Jefyll
Posts: 3525
Joined: 11 Dec 2009
Location: Ontario, Canada
Contact:

Re: Forth Meets AY-3-8912 and Plays Music

Post by Dr Jefyll »

Martin_H wrote:
My Forth chops aren't good enough to handle too much code on a single line. So I have to break it down into chunks I can understand.
Short lines are completely fine -- in fact it's what I prefer myself. It's true that people vary in their preferences, and some are alright with rather dense, lengthy lines. But no way should you strive for that if you find (as I do) that it decreases readability.

Congrats on your project, BTW!

-- Jeff
In 1988 my 65C02 got six new registers and 44 new full-speed instructions!
https://laughtonelectronics.com/Arcana/ ... mmary.html
dwight
Posts: 213
Joined: 08 Jun 2004

Re: Forth Meets AY-3-8912 and Plays Music

Post by dwight »

Instead of:

: DELAY
950 0 DO
LOOP ;

You might use:

: DELAY ( cnt - )
0 DO
950 0 DO
LOOP
LOOP ;

Then you can do

1 DELAY
or
10 DELAY

There is nothing wrong with:

: VC!
VC LATCH C!
WRITE C! ;

Each line is a complete sentence, as it should be.
You should include stack comments though.
User avatar
GARTHWILSON
Forum Moderator
Posts: 8773
Joined: 30 Aug 2002
Location: Southern California
Contact:

Re: Forth Meets AY-3-8912 and Plays Music

Post by GARTHWILSON »

ms (for milliseconds delay) is a standard Forth word. It even made it into ANS Forth. You can do for example

Code: Select all

   100 ms
for a 100ms delay. (Actually ANS shows it in all capitals; but although I mostly want all cap.s for programming, this is an exception, so tha it really does look like "milliseconds" rather than "mega-siemens," siemens (symbolized by the capital letter S) being the derived unit of electric conductance, electric susceptance, and electric admittance in the International System of Units (SI). Conductance, susceptance, and admittance are the reciprocals of resistance, reactance, and impedance, respectively.)
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?
dwight
Posts: 213
Joined: 08 Jun 2004

Re: Forth Meets AY-3-8912 and Plays Music

Post by dwight »

How fast would a 1 henry coil decay to 50% of the
current with a resistance of 1 mega siemens.
Dwight
User avatar
GARTHWILSON
Forum Moderator
Posts: 8773
Joined: 30 Aug 2002
Location: Southern California
Contact:

Re: Forth Meets AY-3-8912 and Plays Music

Post by GARTHWILSON »

About a week. I need the contact info for your inductor supplier! :lol:
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?
Post Reply