Sound

by Ciaran McCreesh
Created: 15th December 1999
Last Modified: 15th December 1999

Sound is possible on the ti86 using the linkport. It is not widely used as few teachers are stupid enough not to notice you're wearing headphones in class (although some really are that blind...) but it adds that touch to your games that'll ensure a Program of the Month award from ticalc.org - greyscale used to do this but it's become too common.

Playing Sound

To play sound from your calculator you either need 2.5mm Stereo Headphones (rare) or a 2.5mm <-> 3.5mm Stereo adaptor. The latter is available for about 70p (about 1 US dollar) from Maplin (UK) or Tandy / Radio Shack (UK and US). You can then simply plug the headphones into the linkport socket and hear sound. Note that your calculator may freeze for a second or two if you plug the headphones in when you're on the homescreen.

What is Sound?

Sound is just changes in pressure in the air. This is generated through headphones by a rapidly moving disc or similar. The purest form of sound uses a sine wave, as illustrated in the diagram. However, as we only have digital control of the linkport we can only generate a square wave, also in the diagram. This generates a slightly tinny sound. If you're a real purist you could attach two capacitors to your headphones to round off the square waves, but that's a bit OTT.

The frequency of a sound affects how high or low it is. This is shown in the lower half of the diagram below. The higher the frequency (number of 'cycles' per second, measured in Hz or Hertz) the higher the note. If you double the frequency you make a note one octave higher (playing games in physics when this was being explained lost me a mark in the prelims, grrr...) and if you half it you go down an octave.

One other thing to note is that the _pause, _getky and _getkey ROM calls will not work properly when the linkport is being used.

Diagram showing Sine and Square waves.

Generating Sound

We can generate sound by switching on and off the linkport rapidly. The code to do this is simple - you just need a delay loop of the required value and then toggle the status of the linkport. The problem is that higher frequency notes take longer to play, so playing notes of the same length requires more complicated maths. I recommend using the cpl instruction to take the one's complement of the delay loop counter and looping that many times.

General Sound Routine

The code below was written by me. It plays a sound out of the linkport. It takes an input in a which determines the frequency (high number, high frequency). It destroys af, bc and de but does not change hl, so you can use hl as a pointer to sound data, for example. I suggest disabling interrupts before calling this routine to get the best sound.

PlaySound:
  ld d,a                  ; value for NumberLoop
  cpl                     ; calculate value for FrequencyLoop
  ld c,a                  ; value for FrequencyLoop
  ld a,%11000000          ; value to send to linkport
  ld e,%00111100          ; value to toggle a with

NumberLoop:
  ld b,c                  ; restore FrequencyLoop counter
FrequencyLoop:
  djnz FrequencyLoop      ; FrequencyLoop is to generate a delay
                          ; before toggling linkport status

  xor e                   ; toggle a with e...
  out (7),a               ; ...and write a to linkport
  dec d                   ; decrease NumberLoop counter
  jr nz,NumberLoop        ; NumberLoop is to ensure that all
                          ; notes are roughly the same length.