|
|
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: #define DRAINTICKS 770 /* how long till the squawker's internal buffer is drained */ ! 17: ! 18: #define SF_LEN 32 /* length of sound fifo */ ! 19: ! 20: long lbolt; ! 21: extern int mmticks; ! 22: ! 23: /* sound control variables, console only */ ! 24: int sdtm_click = 1000; ! 25: int sdtm_charwait = 7200; ! 26: int sdtm_topcr = 370; ! 27: int sdtm_botcr = 50; ! 28: int sdtm_inccr = 3; ! 29: int sdnoises = 1, sdtones = 0; ! 30: ! 31: static short sf_fifo[SF_LEN]; ! 32: static int sf_head, sf_tail; ! 33: static long wait_lbolt; ! 34: ! 35: static freqset(freq) ! 36: int freq; ! 37: { ! 38: short istate; ! 39: istate = sphi(); ! 40: if(freq < 0) /* turn off tone */ ! 41: outb(0x61, inb(0x61) & ~1); ! 42: else { ! 43: outb(0x43, 0xb6); ! 44: outb(0x42, freq); ! 45: outb(0x42, (freq>>8)); ! 46: outb(0x61, inb(0x61) | 3); ! 47: } ! 48: spl(istate); ! 49: } /* freqset */ ! 50: ! 51: static putfifo(p) ! 52: short *p; ! 53: { ! 54: short istate; ! 55: int i; ! 56: ! 57: istate = sphi(); ! 58: i = sf_head; ! 59: while(*p) { ! 60: sf_fifo[i++] = *p++; ! 61: if(i == SF_LEN) i = 0; ! 62: if(i == sf_tail) goto done; ! 63: } ! 64: sf_head = i; ! 65: ! 66: done: spl(istate); ! 67: } /* putfifo */ ! 68: ! 69: chkfifo() ! 70: { ! 71: int i; ! 72: short freq; ! 73: long l; ! 74: ! 75: if(wait_lbolt) { ! 76: l = lbolt - wait_lbolt; ! 77: if(l >= 0 || l <= -1000) { ! 78: freqset(-1); ! 79: wait_lbolt = 0; ! 80: } ! 81: } ! 82: ! 83: if(!wait_lbolt) { ! 84: if((i = sf_tail) != sf_head) { ! 85: freq = sf_fifo[i++]; ! 86: if(i == SF_LEN) i = 0; ! 87: l = sf_fifo[i++]; ! 88: if(i == SF_LEN) i = 0; ! 89: sf_tail = i; ! 90: freqset(freq); ! 91: wait_lbolt = lbolt + l; ! 92: } ! 93: } ! 94: ! 95: #ifndef MSDOS ! 96: if(wait_lbolt) mmticks = 1; /* higher resolution */ ! 97: #endif ! 98: } /* chkfifo */ ! 99: ! 100: /* generate a sound based on the passed parameter */ ! 101: /* should only be called when the session runs on the console */ ! 102: sdsound(sound) ! 103: { ! 104: short *snd_array; ! 105: static short startsnd[] = { ! 106: 2000,2,1800,2,1700,2,1500,2,1400,2,1300,2,1200,2,1000,2,900,2,800,2,700,2,500,2,0,0}; ! 107: static short bellsnd[] = {662,5,0,0}; ! 108: static short boundsnd[] = {376,3,316,3,0,0}; ! 109: static short offsnd[] = {4800,3,0,0}; ! 110: static short onsnd[] = {2000,10,0,0}; ! 111: static short buzzsnd[] = {8000,20,0,0}; ! 112: static short *soundlist[] = { ! 113: 0, 0, 0, bellsnd, boundsnd, offsnd, onsnd, buzzsnd, startsnd}; ! 114: ! 115: if(!sdnoises) return; ! 116: ! 117: snd_array = soundlist[sound]; ! 118: if(snd_array) ! 119: putfifo(snd_array); ! 120: if(sound == 2) sdcrsnd(); ! 121: if(sound == 1) sdclick(); ! 122: } /* sdsound */ ! 123: ! 124: /* under Coherent, we return an integer that indicates whether ! 125: * the mmtime() function should take a real time break before processing ! 126: * this or subsequent characters. ! 127: * Sometimes the time to wait before creating the click of the next ! 128: * character extends beyond the next system clock interrupt. ! 129: * In this case, there is no point in hogging the CPU. ! 130: * Return 1 to indicate that this character should be held, ! 131: * and acted upon once the mmtime() function is reinvoked ! 132: * at the next system clock interrupt, unless of course there ! 133: * is something else ready to run, such as my wife's word processor ! 134: * or a cron job. ! 135: * A return of 0 means we waited the proper amount of time and made the ! 136: * corresponding noise, and we are ready to receive the next character. ! 137: * If we are running musical output, the tone must persist for approx ! 138: * a tenth of a second. Return 2 to indicate this. */ ! 139: int sdcharsnd(c) ! 140: char c; ! 141: { ! 142: /* lr_notes[i] = 1193181/(1000*1.02^(i+1)) */ ! 143: static short lr_notes[] = { ! 144: 1168,1146,1124,1102,1080,1060,1038,1018,1000,980,960,942,924,906,888,872, ! 145: 854,838,822,806,790,774,760,744,730,716,702,688,674,662,648,636, ! 146: 624,612,600,588,576,566,554,544,532,522,512,502,492,482,474,464, ! 147: 454,446,438,428,420,412,404,396,388,380,374,366,358,352,344,338}; ! 148: ! 149: /* make sound accompanying this character */ ! 150: if(sdtones) { ! 151: #ifdef MSDOS ! 152: while(wait_lbolt || sf_head != sf_tail) ; ! 153: #endif ! 154: ! 155: if(c == 13) sdsound(2); ! 156: if(c >= 96) c -= 32; ! 157: if(c > ' ') freqset(lr_notes[c-' ']); ! 158: #ifdef MSDOS ! 159: wait_lbolt = lbolt + 3; ! 160: #endif ! 161: return 8; ! 162: } /* sdtones */ ! 163: ! 164: if(sdnoises) { ! 165: switch(c) { ! 166: case 7: sdsound(3); break; ! 167: case 13: sdsound(2); break; ! 168: default: ! 169: if(c > ' ') ! 170: sdsound(1); ! 171: break; ! 172: } ! 173: #ifdef MSDOS ! 174: sdpause(sdtm_charwait - sdtm_click); ! 175: #endif ! 176: return 4; ! 177: } /* noises on */ ! 178: ! 179: return 0; ! 180: } /* sdcharsnd */ ! 181: ! 182: /* sound for turning a mode on or off, from within a deferred function */ ! 183: sdonoff(onoff) ! 184: { ! 185: if(!sdsession) ! 186: sdsound(5+onoff); ! 187: } /* sdonoff */ ! 188: ! 189: draincheck(o) ! 190: struct SDCONTROL *o; ! 191: { ! 192: long l; ! 193: ! 194: if(o->drain_lbolt) { ! 195: l = lbolt - o->drain_lbolt; ! 196: if(l < 0 && l > -1000) ! 197: return 1; /* still waiting */ ! 198: o->drain_lbolt = 0; ! 199: } ! 200: ! 201: return 0; ! 202: } /* draincheck */ ! 203: ! 204: drainset(o) ! 205: struct SDCONTROL *o; ! 206: { ! 207: o->drain_lbolt = lbolt + DRAINTICKS; ! 208: } /* drainset */ ! 209: ! 210: #ifndef MSDOS ! 211: /* return nonzero if we need to take a real time break */ ! 212: mmgo1(c) ! 213: int c; ! 214: { ! 215: int rc; /* return value */ ! 216: IO iob; ! 217: ! 218: /* set up for mmgo() */ ! 219: iob.io_seg = IOSYS; ! 220: iob.io_ioc = 1; ! 221: iob.io.vbase = &c; ! 222: iob.io_flag = 0; ! 223: ! 224: mmticks = 1; ! 225: ! 226: rc = sdoutchar(0, c); ! 227: ! 228: if(rc & 2) { ! 229: int c1 = c; ! 230: c = '\33'; ! 231: mmgo(&iob); ! 232: c = c1; ! 233: } ! 234: ! 235: if(rc & 1) mmgo(&iob); ! 236: ! 237: if(rc & 8) { ! 238: mmticks = 8; ! 239: return 0; ! 240: } ! 241: ! 242: if(rc & 4) { ! 243: mmticks = 1; ! 244: return 0; ! 245: } ! 246: ! 247: return 1; ! 248: } /* mmgo1 */ ! 249: ! 250: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.