/* * Copyright 1982 UniSoft Corporation * * Speaker Driver * Used to operate the lisa speaker. */ #include "sys/param.h" #include "sys/config.h" #include "sys/types.h" #include "sys/systm.h" #include "sys/dir.h" #include "sys/signal.h" #include "sys/user.h" #include "sys/errno.h" #include "sys/file.h" #include "sys/tty.h" #include "sys/termio.h" #include "sys/conf.h" #include "sys/sysinfo.h" #include "sys/var.h" #include "sys/reg.h" #include "sys/callo.h" #include "sys/ttold.h" #include "setjmp.h" #include "sys/mmu.h" #include "sys/cops.h" #include "sys/local.h" #include "sys/speaker.h" #include "sys/l2.h" typedef unsigned long u_long; u_long sktrap; /* flag and slot to calculate spkr delay */ int sk_open; /* active flag */ #define SKPRI (PZERO+8) skopen(dev, flag) dev_t dev; { if (dev != 0) { /* minor device number is wrong */ u.u_error = ENXIO; return; } if (flag == 1) { /* open for reading ?? */ u.u_error = EINVAL; return; } if (sk_open++ > 0) { /* already opened */ u.u_error = EBUSY; return; } } /* ARGSUSED */ skclose(dev, flag) { if (sk_open <= 0) u.u_error = EINVAL; else sk_open = 0; } /* ARGSUSED */ skwrite(dev) { struct speaker spkr; while (u.u_count >= sizeof(spkr)) { if (copyin(u.u_base, (caddr_t)&spkr, sizeof(spkr))) { u.u_error = EFAULT; return; } u.u_base += sizeof(spkr); u.u_count -= sizeof(spkr); SPL2(); while (sktrap) (void) sleep((caddr_t)&sktrap, SKPRI); COPSADDR->e_irb = (COPSADDR->e_irb & 0xF1) | ((spkr.sk_volume&7) << 1); sksound(spkr.sk_wavlen&MAXWLEN, spkr.sk_duration); SPL0(); } } /* Produce a sound on the speaker at wavelength w microseconds * for duration d clock ticks */ sksound(w, d) register unsigned w, d; { extern int skquiet(); w &= MAXWLEN; /* max wavelength */ if (w < MINWLEN) w = MINWLEN; sktrap = d; /* call skquiet at now + d */ if (sktrap <= 0) sktrap = 1; /* in case < MILLIRATE */ timeout(skquiet, (caddr_t)0, (int)sktrap); sktone (w); } /* Start a tone at wavelength w microseconds. Sound is produced by rapidly * turning on and off the speaker. The 6522 cops chip has an output to the * speaker connected to a shift register. A built in timer controls the rate * at which the shift register bits are output to the speaker. */ sktone(w) register unsigned w; { register struct device_e *p = COPSADDR; register int cmd = 0x55; /* sk shift reg */ w = w >> 3; /* wavelength resolution is 8 microseconds */ if (w > 0xFF) { cmd = 0x33; w = w >> 1; if (w > 0xFF) { cmd = 0xF; w = w >> 1; } } p->e_acr |= 0x10; /* enable */ p->e_t2cl = w; /* set timer */ p->e_sr = cmd; /* set output pattern */ } skquiet() { struct device_e *p = COPSADDR; p->e_acr &= 0xE3; sktrap = 0; wakeup((caddr_t)&sktrap); } beep() { int sp; if (sktrap) return; sp = spl2(); COPSADDR->e_irb = (COPSADDR->e_irb & 0xF1) | (l2_bvol << 1); sksound((unsigned)l2_bpitch, (unsigned)l2_btime); splx(sp); } #ifdef notdef /* * Produce a short click to implement keyboard clicking */ click() { register struct device_e *p = COPSADDR; int i = 20; int sp; if (sktrap) return; sp = spl2(); p->e_acr |= 0x10; p->e_t2cl = 0x10; p->e_sr = 0x55; while (--i != -1) ; p->e_acr &= 0xE3; splx(sp); } #endif