🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: net.micro.pc
Article #7854

Re: How do you beep?

#7854
From: Matt Landau
Date: Mon, 08 Sep 1986 20:02
210 lines
6602 bytes
Since so many people have remarked on how to make noises with your
IBM PC, I thought I'd just take the simple approach and post the
necessary code.  The following shar file contains sources for a routine
called "sound" which will drive the speaker at a given frequency for
a given time.  It relies on a processor-independent sleep() call, for
which source is also supplied.  This code has been used on PC's, AT's,
and Compaq's, compiled with Lattice 2.15, but there's no reason it
shouldn't work with any Lattice 2.x or 3.x compiler.  Conversion to 
other compilers is straightforward.

Note that the sleep() here is not compatible with the Unix sleep() 
call, since this one works in 1/100's of a second.

Herewith, the source code:

------- CUT HERE ------------------------------------ CUT HERE --------

# This is a shell archive.  Remove anything before this line,
# then unpack it by saving it in a file and typing "sh file".
#
# Wrapped by slate!mlandau on Mon Sep  8 15:55:25 EDT 1986
# Contents:  stdtypes.h sleep.c sound.c
 
echo x - stdtypes.h
sed 's/^XX//' > "stdtypes.h" <<'@//E*O*F stdtypes.h//'
XX/*
XX * S T D T Y P E S . H
XX */

XX#include "dos.h"
XXtypedef int		void;
XXtypedef int		bool;
XXtypedef union REGS	REGS;
XXtypedef struct SREGS	SREGS;
@//E*O*F stdtypes.h//
chmod u=rw,g=rw,o=r stdtypes.h
 
echo x - sleep.c
sed 's/^XX//' > "sleep.c" <<'@//E*O*F sleep.c//'
XX/* 
XX * S L E E P . C
XX * 
XX * Sleep () call for IBM PC, XT, AT.  Depends on timer tick working as
XX * advertised, 18.2 ticks per second.
XX *
XX * This uses int 1A to read the time-of-day clock.  Care is taken to do
XX * something reasonable when the clock rolls over at midnight, so sleep ()
XX * does not bomb late at night.
XX */

XX#include <stdio.h>
XX#include <stdtypes.h>

XX#define TIMER_INT	0x1A
XX#define T_READTIME	0

XX#define SCALE		1000L
XX#define TICKRATE	182L	   /* timer tick rate/100th sec. x scale */
XX#define ROLLOVER	1	   /* est. # of ticks when clock rolls over */
XX#define MKLONG(hi, low)	((long)(((long)hi << 16) | (unsigned)low))


XXvoid	  sleep (how_long)
XXunsigned  how_long;			/* Hundredths of a second */
XX{       
XX	long	this_tick, last_tick;
XX	long	ticks = 0L;
XX	long	count = (long)(TICKRATE * how_long / SCALE);
XX	REGS	r;
XX	
XX	r.h.ah = T_READTIME;
XX	int86 (TIMER_INT, &r, &r);
XX	last_tick = MKLONG (r.x.cx, r.x.dx);
XX	
XX	while (ticks < count)
XX	{       
XX		r.h.ah = T_READTIME;
XX		int86 (TIMER_INT, &r, &r);
XX		this_tick = MKLONG (r.x.cx, r.x.dx);
XX		/* If midnight just passed, assume ROLLOVER ticks */
XX		ticks += (r.h.al == 0) ? this_tick - last_tick : ROLLOVER;
XX		last_tick = this_tick;
XX	}
XX}

@//E*O*F sleep.c//
chmod u=rw,g=rw,o=r sleep.c
 
echo x - sound.c
sed 's/^XX//' > "sound.c" <<'@//E*O*F sound.c//'
XX/* LINTLIBRARY */

XX/* 
XX * S O U N D . C
XX * 
XX * Routines for manipulating the PC speaker.  Since there is no BIOS
XX * interrupt for sound, this code is probably NOT portable.  It relies on
XX * directly controlling the 8255 Programmable Peripheral Interface chip.
XX * 
XX * For reference, I suggest you look at the PC Technical Reference Manual
XX * and at a good book on 8088 assembly language (Scanlon's IBM PC & XT
XX * ASSEMBLY LANGUAGE contains a section on programming the speaker.)
XX */

XX#include <stdio.h>
XX#include <stdtypes.h>


XX#define HZ		1193180		/* system clock is 1.19 MHz      */
XX#define T_BASE		0x40		/* 8253 timer port 0	         */
XX#define T_TONE		(T_BASE + 2)	/* 8253 port 2 controls spkr     */
XX#define T_CONTROL	(T_BASE + 3)	/* 8253 control port addr.       */
XX#define	TIMERDIV(freq)	((unsigned)(HZ/freq)) 	/* Timer divisior        */
XX#define ENABLE_TIMER	182		/* MAGIC NUM from BIOS listing   */
XX#define OUT_8255	0x61		/* 8255 PPI output port address  */
XX#define SPKRBITS	3		/* Bit 0 = control spkr by timer */
XX 					/* Bit 1 = speaker on/off        */

XXextern byte	inp(), outp();		/* Read, write ports */

XX/* 
XX * spkr_on -- turn on the speaker 
XX */

XXstatic
XXvoid	  spkr_on (divisor)
XXunsigned  divisor;
XX{       
XX	byte	status, div;
XX	
XX	status = inp (OUT_8255);		/* get current status */
XX	outp (T_CONTROL, ENABLE_TIMER);
XX	div = divisor & 0xFF;			/* low byte of divisor */
XX	outp (T_TONE, div);
XX	div = (divisor >> 8) & 0xFF;		/* high byte of divisor */
XX	outp (T_TONE, div);
XX	outp (OUT_8255, (status | SPKRBITS));	/* turn on speaker */
XX}

XX/* 
XX * spkr_off -- turn off the speaker
XX */

XXstatic
XXvoid	spkr_off ()
XX{       
XX	byte	status;
XX	
XX	status = inp (OUT_8255);		/* get current status */
XX	outp (OUT_8255, (status & ~SPKRBITS));	/* turn speaker off */
XX}


XX/* 
XX * sound (freq, dur)
XX * 
XX * Make a noise of the given frequency (which may be 37 - 32767 Hz) for the
XX * given duration, in tenths of a second.
XX */
XX 
XXvoid	sound (freq, dur)
XXunsigned freq, dur;
XX{       
XX	extern void	sleep();
XX	
XX	spkr_on (TIMERDIV (freq));
XX	sleep (dur);
XX	spkr_off ();
XX}


XXvoid	beep_low ()
XX{       
XX	sound (440, 15);
XX}


XXvoid	beep ()
XX{       
XX	sound (660, 15);
XX}


XXvoid	beep_high ()
XX{       
XX	sound (880, 15);
XX}

@//E*O*F sound.c//
chmod u=rw,g=rw,o=r sound.c
 
echo Inspecting for damage in transit...
temp=/tmp/shar$$; dtemp=/tmp/.shar$$
trap "rm -f $temp $dtemp; exit" 0 1 2 3 15
cat > $temp <<\!!!
       9      29     139 stdtypes.h
      46     196    1183 sleep.c
     107     425    2491 sound.c
     162     650    3813 total
!!!
wc  stdtypes.h sleep.c sound.c | sed 's=[^ ]*/==' | diff -b $temp - >$dtemp
if [ -s $dtemp ]
then echo "Ouch [diff of wc output]:" ; cat $dtemp
else echo "No problems found."
fi
exit 0
-- 
 Matt Landau      	 		BBN Laboratories, Inc.
    mlandau@diamond.bbn.com		10 Moulton Street, Cambridge MA 02238
 ...harvard!diamond.bbn.com!mlandau     (617) 497-2429
Technical Details
Message-ID: <704@Diamond.BBN.COM>
Path: arc1-ca.pugleaf.net!utzoo!mnetor!seismo!ut-sally!husc6!Diamond!mlandau
References: <23900032@siemens.UUCP> <268@neoucom.UUCP>

Show Full Headers
Complete Article Headers
Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP
Path: arc1-ca.pugleaf.net!utzoo!mnetor!seismo!ut-sally!husc6!Diamond!mlandau
From: mlandau@Diamond.BBN.COM (Matt Landau)
Newsgroups: net.micro.pc
Subject: Re: How do you beep?
Message-ID: <704@Diamond.BBN.COM>
Date: Mon, 8-Sep-86 16:02:14 EDT
Article-I.D.: Diamond.704
Posted: Mon Sep  8 16:02:14 1986
Date-Received: Tue, 9-Sep-86 06:03:46 EDT
References: <23900032@siemens.UUCP> <268@neoucom.UUCP>
Reply-To: mlandau@Diamond.BBN.COM (Matt Landau)
Organization: BBN Labs, Cambridge, MA
Lines: 210
Summary: Code to drive the speaker for Lattice 2.X/3.X