|
|
1.1 ! root 1: /*----------------------------------------------------------------------------- ! 2: Talking BIOS device driver for the AT&T PC6300. ! 3: Copyright (C) Karl Dahlke 1987 ! 4: This software may be freely used and distributed ! 5: for any non-profit purpose. ! 6: *----------------------------------------------------------------------------- ! 7: */ ! 8: ! 9: /* noises.c: generate sounds */ ! 10: ! 11: #ifndef MSDOS ! 12: #include <sys/io.h> ! 13: #endif ! 14: #include "speech.h" ! 15: ! 16: /* intervals, measured in ticks of the timer */ ! 17: #define TICKS_CYCLE 11932 ! 18: #define TICKS_CLICK 1000 ! 19: #define TICKS_CHARWAIT 7200 ! 20: #define TICKS_TOPCR 560 ! 21: #define TICKS_BOTCR 64 ! 22: #define TICKS_INCCR 5 ! 23: ! 24: #define DRAINTICKS 770 /* how long till the squawker's internal buffer is drained */ ! 25: ! 26: #define SF_LEN 32 /* length of sound fifo */ ! 27: ! 28: long lbolt; ! 29: extern int mmticks; ! 30: ! 31: /* sound control variables, console only */ ! 32: int sdnoises = 1, sdtones = 0; ! 33: ! 34: static short sf_fifo[SF_LEN]; ! 35: static int sf_head, sf_tail; ! 36: static long wait_lbolt; ! 37: ! 38: static freqset(freq) ! 39: int freq; ! 40: { ! 41: short istate; ! 42: istate = sphi(); ! 43: if(freq < 0) /* turn off tone */ ! 44: outb(0x61, inb(0x61) & ~1); ! 45: else { ! 46: outb(0x43, 0xb6); ! 47: outb(0x42, freq); ! 48: outb(0x42, (freq>>8)); ! 49: outb(0x61, inb(0x61) | 3); ! 50: } ! 51: spl(istate); ! 52: } /* freqset */ ! 53: ! 54: static putfifo(p) ! 55: short *p; ! 56: { ! 57: short istate; ! 58: int i; ! 59: ! 60: istate = sphi(); ! 61: i = sf_head; ! 62: while(*p) { ! 63: sf_fifo[i++] = *p++; ! 64: if(i == SF_LEN) i = 0; ! 65: if(i == sf_tail) goto done; ! 66: } ! 67: sf_head = i; ! 68: ! 69: done: spl(istate); ! 70: } /* putfifo */ ! 71: ! 72: chkfifo() ! 73: { ! 74: int i; ! 75: short freq; ! 76: long l; ! 77: ! 78: if(wait_lbolt) { ! 79: l = lbolt - wait_lbolt; ! 80: if(l >= 0 || l <= -1000) { ! 81: freqset(-1); ! 82: wait_lbolt = 0; ! 83: } ! 84: } ! 85: ! 86: if(!wait_lbolt) { ! 87: if((i = sf_tail) != sf_head) { ! 88: freq = sf_fifo[i++]; ! 89: if(i == SF_LEN) i = 0; ! 90: l = sf_fifo[i++]; ! 91: if(i == SF_LEN) i = 0; ! 92: sf_tail = i; ! 93: freqset(freq); ! 94: wait_lbolt = lbolt + l; ! 95: } ! 96: } ! 97: ! 98: #ifndef MSDOS ! 99: if(wait_lbolt && mmticks == 10) mmticks = 1; /* higher resolution */ ! 100: #endif ! 101: } /* chkfifo */ ! 102: ! 103: /* generate a sound based on the passed parameter */ ! 104: /* should only be called when the session runs on the console */ ! 105: sdsound(sound) ! 106: { ! 107: short *snd_array; ! 108: static short startsnd[] = {2000,10,1500,10,1333,10,1123,10,0,0}; ! 109: static short bellsnd[] = {662,5,0,0}; ! 110: static short boundsnd[] = {376,3,316,3,0,0}; ! 111: static short offsnd[] = {4800,3,0,0}; ! 112: static short onsnd[] = {2000,10,0,0}; ! 113: static short buzzsnd[] = {8000,20,0,0}; ! 114: static short *soundlist[] = { ! 115: 0, 0, 0, bellsnd, boundsnd, offsnd, onsnd, buzzsnd, startsnd}; ! 116: ! 117: if(!sdnoises) return; ! 118: ! 119: snd_array = soundlist[sound]; ! 120: if(snd_array) ! 121: putfifo(snd_array); ! 122: if(sound == 2) crsnd(); ! 123: if(sound == 1) spk_click(); ! 124: } /* sdsound */ ! 125: ! 126: /* under Coherent, we return an integer that indicates whether ! 127: * the mmtime() function should take a real time break before processing ! 128: * this or subsequent characters. ! 129: * Sometimes the time to wait before creating the click of the next ! 130: * character extends beyond the next system clock interrupt. ! 131: * In this case, there is no point in hogging the CPU. ! 132: * Return 1 to indicate that this character should be held, ! 133: * and acted upon once the mmtime() function is reinvoked ! 134: * at the next system clock interrupt, unless of course there ! 135: * is something else ready to run, such as my wife's word processor ! 136: * or a cron job. ! 137: * A return of 0 means we waited the proper amount of time and made the ! 138: * corresponding noise, and we are ready to receive the next character. ! 139: * If we are running musical output, the tone must persist for approx ! 140: * a tenth of a second. Return 2 to indicate this. */ ! 141: int sdcharsnd(c) ! 142: char c; ! 143: { ! 144: /* lr_notes[i] = 1193181/(1000*1.02^(i+1)) */ ! 145: static short lr_notes[] = { ! 146: 1168,1146,1124,1102,1080,1060,1038,1018,1000,980,960,942,924,906,888,872, ! 147: 854,838,822,806,790,774,760,744,730,716,702,688,674,662,648,636, ! 148: 624,612,600,588,576,566,554,544,532,522,512,502,492,482,474,464, ! 149: 454,446,438,428,420,412,404,396,388,380,374,366,358,352,344,338}; ! 150: ! 151: /* make sound accompanying this character */ ! 152: if(sdtones) { ! 153: #ifdef MSDOS ! 154: while(wait_lbolt || sf_head != sf_tail) ; ! 155: #endif ! 156: ! 157: if(c == 13) sdsound(2); ! 158: if(c >= 96) c -= 32; ! 159: freqset(-1); ! 160: if(c > ' ') freqset(lr_notes[c-' ']); ! 161: wait_lbolt = lbolt + 5; ! 162: return 8; ! 163: } /* sdtones */ ! 164: ! 165: if(sdnoises) { ! 166: switch(c) { ! 167: case 7: sdsound(3); break; ! 168: case 13: sdsound(2); break; ! 169: default: ! 170: if(c > ' ') ! 171: sdsound(1); ! 172: #ifdef MSDOS ! 173: else ! 174: sdpause(TICKS_CLICK); ! 175: #endif ! 176: break; ! 177: } ! 178: #ifdef MSDOS ! 179: sdpause(TICKS_CHARWAIT - TICKS_CLICK); ! 180: #endif ! 181: return 4; ! 182: } /* noises on */ ! 183: ! 184: return 0; ! 185: } /* sdcharsnd */ ! 186: ! 187: /* sound for turning a mode on or off, from within a deferred function */ ! 188: sdonoff(onoff) ! 189: { ! 190: if(!sdsession) ! 191: sdsound(5+onoff); ! 192: } /* sdonoff */ ! 193: ! 194: draincheck() ! 195: { ! 196: long l; ! 197: ! 198: if(sdc->drain_lbolt) { ! 199: l = lbolt - sdc->drain_lbolt; ! 200: if(l < 0 && l > -1000) ! 201: return 1; /* still waiting */ ! 202: sdc->drain_lbolt = 0; ! 203: } ! 204: ! 205: return 0; ! 206: } /* draincheck */ ! 207: ! 208: drainset(o) ! 209: struct SDCONTROL *o; ! 210: { ! 211: o->drain_lbolt = lbolt + DRAINTICKS; ! 212: } /* drainset */ ! 213: ! 214: /* togle the inbuilt speaker */ ! 215: static spk_toggle() ! 216: { ! 217: short istate = sphi(); ! 218: char c; ! 219: c = inb(0x61); ! 220: /* cannot interrupt a tone with a click */ ! 221: if(!(c&1)) ! 222: outb(0x61, c^2); ! 223: spl(istate); ! 224: } /* spk_toggle */ ! 225: ! 226: /* pause this many clock ticks */ ! 227: sdpause(nticks) ! 228: { ! 229: int t0val = read_t0(); ! 230: int nextval; ! 231: do { ! 232: nextval = read_t0(); ! 233: t0val -= nextval; ! 234: #ifndef MSDOS ! 235: if(t0val < 0) t0val += TICKS_CYCLE; ! 236: #endif ! 237: nticks -= t0val; ! 238: t0val = nextval; ! 239: } while(nticks > 0); ! 240: } /* sdpause */ ! 241: ! 242: /* the sound of a character click */ ! 243: static spk_click() ! 244: { ! 245: spk_toggle(); ! 246: sdpause(TICKS_CLICK); ! 247: spk_toggle(); ! 248: } /* spk_click */ ! 249: ! 250: crsnd() ! 251: { ! 252: int i, nticks, nextval; ! 253: int t0val = read_t0(); ! 254: ! 255: for(i=TICKS_TOPCR; i>TICKS_BOTCR; i-=TICKS_INCCR) { ! 256: spk_toggle(); ! 257: nticks = i; ! 258: do { ! 259: nextval = read_t0(); ! 260: t0val -= nextval; ! 261: #ifndef MSDOS ! 262: if(t0val < 0) t0val += TICKS_CYCLE; ! 263: #endif ! 264: nticks -= t0val; ! 265: t0val = nextval; ! 266: } while(nticks > 0); ! 267: } ! 268: } /* crsnd */ ! 269: ! 270: #ifndef MSDOS ! 271: /* return nonzero if we need to take a real time break */ ! 272: mmgo1(c) ! 273: int c; ! 274: { ! 275: int rc; /* return value */ ! 276: IO iob; ! 277: ! 278: /* set up for mmgo() */ ! 279: iob.io_seg = IOSYS; ! 280: iob.io_ioc = 1; ! 281: iob.io.vbase = &c; ! 282: iob.io_flag = 0; ! 283: ! 284: mmticks = 1; ! 285: ! 286: rc = sdoutchar(0, c); ! 287: ! 288: if(rc & 2) { ! 289: int c1 = c; ! 290: c = '\33'; ! 291: mmgo(&iob); ! 292: c = c1; ! 293: } ! 294: ! 295: if(rc & 1) mmgo(&iob); ! 296: ! 297: if(rc & 8) { ! 298: mmticks = 7; ! 299: return 1; ! 300: } ! 301: ! 302: if(rc & 4) { ! 303: mmticks = 1; ! 304: return 2; ! 305: } ! 306: ! 307: return 0; ! 308: } /* mmgo1 */ ! 309: ! 310: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.