• Please review our updated Terms and Rules here

How does audio on the TRS-80 Model 1 work?

psuedo

New Member
Joined
Jan 13, 2024
Messages
3
Good evening all,

I'm trying to figure out how audio works on the TRS 80 Model 1 from a software perspective.

I don't have a model 1, but I'd like to understand the theory behind generating tones via the cassette port so that I may apply the same method to machines that I do have:

TRS 80 Model 100
TRS 80 Model 4 (I can't afford the sound card right now, so I'd like to try to run sound through the cassette port instead)
NEC PC-8001 (stretch goal)


The end goal is duophonic sound through software, like what we hear in frogger:


I've been analyzing this program for reference:



The BASIC portions i mostly get, however the machine language code is stumping me. Before I started this, I didn't know any Z80 assembler at all. I converted the BASIC DATA statements in the program into a BIN file with a python script, and ran it through two separate disassemblers (to make sure they match up) and got this code from both of them:

push af push bc push de push hl ld de,(7f8dh) 0ld a,(7f92h) ld b,a ld c,00h push bc ld a,02h call 7fcbh ld a,01h call 7fcbh pop bc djnz 000eh ld hl,(7f8ah) ld bc,007fh or a sbc hl,bc ld bc,(7f90h) add hl,bc ld (7f8ah),hl dec de ld a,d or e jr nz,0008h pop hl pop de pop bc pop af ret ld bc,(7f8ah) out (0ffh),a dec bc ld a,b or c jr nz,003dh ret

After spending some time reading over some Z80 tutorials and guides, i annotated about half of this code with comments for what each line is doing to the best of my ability. However, I still feel like I'm missing something in my understanding.

Switching gears - my model 100 is the only machine I have fully available and functional at the moment, so I tried to see if i could get any sound out of the cassette port at all (i know BASIC is slow, but i was at least hoping for a low buzz to confirm it was possible before i start doing stuff in z88dk).

After some testing, I was able to get a little buzz out of... something (something near the cassette port and not the built in speaker?) when i run the following BASIC script.. however it sounds distressing and I feel like I'm damaging the machine when I do this:

motoron port = 226 ' 226-239 all make the same sound for x = 1 to 40 out port, 40 out port,0 next x motoroff

I read through parts of the Model 100's technical reference manual, especially the parts regarding the cassette interface, and I am still somewhat lost.

Sorry if this post is kind of all over the place, but I'm not super experienced here and would like to learn more about how the sound generation works. If anyone could explain to me the process on the model 1 of just creating a single square wave, I'd be very grateful!

Thank you!
 
You're on the right track.
Simply, just hammer the port with variable width pulses. (PWM) at an acceptable sample rate.
At first when learning just play with fixed 50% duty cycle square waves of different frequencies.
Start with about 200Hz and work up to 2000Hz.
Once you're comfortable with that then you can work up to much faster sample rates with variable duty cycles to produce an analogue signal where the speaker and audio circuit effectively averages out the variable pulses to analogue voltages.
 
You're on the right track.
Simply, just hammer the port with variable width pulses. (PWM) at an acceptable sample rate.
At first when learning just play with fixed 50% duty cycle square waves of different frequencies.
Start with about 200Hz and work up to 2000Hz.
Once you're comfortable with that then you can work up to much faster sample rates with variable duty cycles to produce an analogue signal where the speaker and audio circuit effectively averages out the variable pulses to analogue voltages.
thank you! I will experiment with this
 
There's 2 ways of getting sound out of a model 1.
1. Turn the cassette relay on and off quickly so that it buzzes. There's a range of frequencies that can be made, but of course it doesn't work on emulators.
2. Send a tone through the cassette output line. You have 2 loops, the inner loop sets the frequency, and the outer loop sets the length of the tone.
The inner loop will have a timer to set the signal on, and then the same amount of time to set the signal off. This ensures 50% duty cycle.
 
After some testing, I was able to get a little buzz out of... something (something near the cassette port and not the built in speaker?) when i run the following BASIC script.. however it sounds distressing and I feel like I'm damaging the machine when I do this:

FWIW, what you’re doing to your Model 100 is rapidly pulsing the cassette remote motor control relay, not tickling the cassette sound output. Which, per point #1 from @Robbbert , is also a thing you can do on the Model I/III/4, but, yes, I personally wouldn’t make too much of a habit out of it.

Be aware, of course, that the hardware is completely different between the Model 100 and the desktop TRS-80s, they don’t even use the same CPUs, so anything you write for one will need a lot of changes to move to the other. I took a quick look at the model 100 tech manual and it looks like cassette audio is modulated by the 8085 CPU’s SOD pin, which the Z80 doesn’t even have, and is fiddled using instructions unique to the Intel chip. I don’t know enough about the serial lines on the 8085 to say if there’s any dealbreakers to outputting arbitrary waveforms through it; my guess is not, but… again? Different hardware from the Model I/III/4.
 
3. put an AM radio next to it, sounds made using method 2 will usually be easy to hear

Of course if you’re doing the AM radio thing banging on *any* hardware is optional, just run the delay loops. For laughs I recently ported a kinda famous tiny 200-ish byte program for the original Altair 8800 to my TRS-80 and made a YouTube short of the audio playing.

See post in thread 'Programming Altair confusion':
https://forum.vcfed.org/index.php?threads/programming-altair-confusion.1245626/post-1350173

Again, there’s no wire between the computer and the boombox, it’s just RF interference.
 
The AM radio and other spurious emissions from home computers caused TVI and other safety issues which forced the appropriate FCC and worldwide equivalent regulations to be formulated.
Welcome to the world of EMC (electromagnetic compliance)!
 
Be aware, of course, that the hardware is completely different between the Model 100 and the desktop TRS-80s, they don’t even use the same CPUs, so anything you write for one will need a lot of changes to move to the other. I took a quick look at the model 100 tech manual and it looks like cassette audio is modulated by the 8085 CPU’s SOD pin, which the Z80 doesn’t even have....
For the purposes of generating sound like this I wouldn't call the hardware "completely different"; in fact it's pretty much the same.

The 8085 and the Z80 share a large set of compatible instructions (the 8080 ones) that cover everything you need to bit-bang I/O pins to produce square waves. So there's no worries there.

On the Model I you need to change bit 0 on I/O port $FF to toggle the CMT output between 0.85 V and 0 V. That's a simple OUT instruction. (Well, not totally simple, given that other bits in the port control the CMT relay and the 64/32 column mode, but so long as you consistently use 0s for those, you should be fine, I think. TRS-80 Model I experts should correct me if I'm wrong.)

On the Model 100 you toggle the CMT output in a different way: it's on the serial output pin of the 8085 so you load the A register with %0100,0000 ($40) and execute a SIM instruction to set that bit off, and use A register with %1100,0000 ($C0) to set that bit on. Here, bit 7 is the value for the output, and bit 6 being set to 1 indicates that you want bit 7 to be used to set the output. All other bits 0 means you don't want anything else controlled by SIM (interrupts, basically) to be changed.

So in both cases above, the specific values you load into A and the specific instruction you use to set the output pin (OUT vs SIM) are different, but all the rest is the same. (Well, the timing delays you use will change as well, of course.)
 
For the purposes of generating sound like this I wouldn't call the hardware "completely different"; in fact it's pretty much the same.

Sure they are, in that ultimately you have some analog circuitry just rounding the edges off a bit-banged I/O port. My point was mostly about how you actually toggle that port is different, IE, all the hardware addresses differ. The framework around the I/O part could certainly be mostly shared, although the fact you only have access to 8080 instructions could well be significant if you’re trying to reference code that was written for the Model I in the first place.

FWIW, if you’re targeting a Model 100 it *does* have a built-in speaker/buzzer hanging off a bit of the 81C55 I/O chip, and you have two options to toggle it; you can manually bang the drive transistor on and off with OUT commands, which would let you treat it essentially the same as the cassette port, or you can have it sound a tone regulated by the I/O chip’s timer frequency. (Similar to how sound works in an IBM PC. Or maybe more like the VIA sound method in a Commodore PET?) You don’t *have* to use the cassette port with a separate amp. Granted the buzzer is pretty lo-fi.
 
Last edited:
The AM radio and other spurious emissions from home computers caused TVI and other safety issues which forced the appropriate FCC and worldwide equivalent regulations to be formulated.
Welcome to the world of EMC (electromagnetic compliance)!

The AM sound thing is kind of impractical if you were writing a game or whatever anyway, because the thing about the Model I is the RF emission is so bad you’re going to hear *everything* it’s doing; the sound loops will be there, but so will be all the chirps and whistles from your game logic, updating the screen…

Which is actually kind of cool. Keeping an AM radio handy is a pretty good way to tell if your Model I has gone into an endless loop or crashed…
 
My point was mostly about how you actually toggle that port is different, IE, all the hardware addresses differ.
Yeah, that's a pretty minor difference, just a couple of instructions that need to be changed, really. Not what I would call "completely different" in code that consists of many dozens or even hundreds of instructions.

Your point about the Model I code using Z80 extensions may or may not be valid; it depends on whether the code to be ported is actually using any of those. The code quoted in the first post uses DJNZ, but that's pretty easy to convert back to 8080.
 
Well people, I did it!

After fixing my TRS 80 Model 4, I've been able to do some more experimenting, and I figured out how to get sound out of it!

I was going through the assembler code again, and found that port 0ffh on is the cassette port on the Model 1. I went into Model III BASIC (all my OS disks are fried, I didn't know about the floppy disk eating problem and destroyed all my disks without realizing) and wrote this program:

Code:
10 OUT 255,1
20 OUT 255,0
30 GOTO 10

This produced a tone on the cassette's output, and I was able to hear it though my cassette recorder. After my FreHD arrives, I'll expand on this in C and push for manipulating the frequency a bit. But in the meantime, I'll continue tinkering with BASIC. Thanks for your help everyone!

As for the Model 100, it seems like the way it does audio is a bit more involved than I expected, and will take some more diving into the manual to fully understand.

Thanks again!
 
Back
Top