Hello all.
Over the weekend I got bored and wanted something fun to toy with. Well, I have an old 486 laptop, a copy of Turbo C and nerves of steel. I wanted to learn how to make sounds and project them out the PC speaker.
After some research and experimentation, I was able to write a program that sets the countdown period of timer 2 and connects it to the PC speaker to produce sound:
And...it works! Just not on the laptop. It hangs at line 39 where it tries to read port 61h and gets no further. Meanwhile if I run the same binary in DOSBox it happily skips up the D major scale like its supposed to.
Maybe I'm missing something simple. Messing with hardware even on a simple level like this is a bit new to me so its possible. I guess I'm just looking for a nudge in the right direction.
Thoughts?
Over the weekend I got bored and wanted something fun to toy with. Well, I have an old 486 laptop, a copy of Turbo C and nerves of steel. I wanted to learn how to make sounds and project them out the PC speaker.
After some research and experimentation, I was able to write a program that sets the countdown period of timer 2 and connects it to the PC speaker to produce sound:
#include <stdio.h> #include <conio.h> int main(void) { /* Declare PIT variables. */ int freqs[] = { 294, 330, 367, 392, 440, 494, 554, 587 }; int countdown = 1193180 / 294; int lowerbyte = countdown & 0xff; int higherbyte = (countdown >> 8) & 0xff; int connected = 0; int x = 0; unsigned int value = 0; int period = 500; /* Here we go... */ printf("Making beep sounds...\n\n"); getchar(); while ( x < 8 ) { /* Adjust the countdown for the new frequency. */ countdown = 1193180 / freqs[x]; lowerbyte = countdown & 0xff; higherbyte = ( countdown >> 8 ) & 0xff; /* Set the timer. */ printf( "Setting new frequency of %d Hz.\n", freqs[x] ); outportb( 0x43, 0x6b ); outportb( 0x42, lowerbyte ); outportb( 0x42, higherbyte ); /* Connect to the speaker, if not already connected. */ if ( connected == 0 ) { printf( "Connecting to the speaker.\n" ); getchar(); printf( "Connecting...\n" ); /* Get the value of the port. Set bits 0 and 1 of the control byte. */ value = inportb( 0x61 ); printf( "Value of the speaker port is %d. Adjust mode for timer connection.\n", value ); value = value | 3; printf( "Value is now %d. Setting the control byte.\n", value); getchar(); /* Connect to speaker. */ outportb( 0x61, value ); printf( "Connected.\n" ); connected++; } /* Sleep a while. */ printf( "Sleeping... " ); delay(period); printf( "done.\n" ); x++; } /* Disconnect the speaker from the timer and reset the port. */ printf( "Disconnecting the speaker... " ); value = inportb( 0x61 ); value = value & 0xfc; outportb( 0x61, value ); printf( "done.\n" ); /* Declare we are done. */ printf( "Sound test done.\n" ); return 0; }
And...it works! Just not on the laptop. It hangs at line 39 where it tries to read port 61h and gets no further. Meanwhile if I run the same binary in DOSBox it happily skips up the D major scale like its supposed to.
Maybe I'm missing something simple. Messing with hardware even on a simple level like this is a bit new to me so its possible. I guess I'm just looking for a nudge in the right direction.
Thoughts?