|
|
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: /* synth.c: interface functions to the speech synthesizer */ ! 10: ! 11: #include "speech.h" ! 12: ! 13: #ifdef MSDOS ! 14: /* taken from Coherent ins8250.h */ ! 15: #define DREG 0 /* Data Register (DLAB=0) */ ! 16: #define IER 1 /* Interrupt Enable Register (DLAB=0) */ ! 17: #define IIR 2 /* Interrupt Identification Register */ ! 18: #define FCR 2 /* FIFO Control Register */ ! 19: #define LCR 3 /* Line Control Register */ ! 20: #define MCR 4 /* Modem Control Register */ ! 21: #define LSR 5 /* Line Status Register */ ! 22: #define MSR 6 /* Modem Status Register */ ! 23: #define SCR 7 /* Scratch Register */ ! 24: #else ! 25: #include <sys/ins8250.h> ! 26: #endif ! 27: ! 28: #define LDLR 0 /* low divisor latch */ ! 29: #define HDLR 1 /* high divisor latch */ ! 30: ! 31: #ifdef MSDOS ! 32: static int AL_ADDR[] = {0x3f8, 0x2f8, 0x3e8, 0x2e8}; ! 33: #else ! 34: extern int AL_ADDR[]; ! 35: extern int C1BAUD, C2BAUD, C3BAUD, C4BAUD, albaud[]; ! 36: #endif ! 37: ! 38: int sdoverride; /* override bad signals */ ! 39: ! 40: static int crticks, deadbuzz, inxmit; ! 41: static char *xmit_ptr; ! 42: static int i_comport; /* com port with the interrupt active */ ! 43: static short i_combase; /* AL_ADDR[i_comport-1]; */ ! 44: static struct SDCONTROL *i_sdc; ! 45: ! 46: /* init the synthesizer */ ! 47: sdsynth_init(session) ! 48: short session; ! 49: { ! 50: short istate; ! 51: int synth, comport; ! 52: int baud; ! 53: extern int sdintr(); ! 54: ! 55: synth = (&sd0synth)[session]; ! 56: comport = (&sd0comport)[session]; ! 57: /* range check synth and comport */ ! 58: if(synth < 1 || synth > 1 || ! 59: comport < 1 || comport > 4 || ! 60: comport && i_comport) ! 61: return 0; ! 62: ! 63: sdcontrol[session] = i_sdc = (struct SDCONTROL *) kalloc(sizeof(struct SDCONTROL)); ! 64: if(!i_sdc) return; /* kalloc failed */ ! 65: memset(i_sdc, 0, sizeof(struct SDCONTROL)); ! 66: ! 67: if(comport) { /* unit is on a serial port */ ! 68: i_comport = comport; ! 69: i_combase = AL_ADDR[comport-1]; ! 70: ! 71: istate = sphi(); ! 72: /* initialize the UART */ ! 73: /* no transmit interrupt until we start sending text */ ! 74: outb(i_combase+IER, 0); ! 75: outb(i_combase+MCR, 0); ! 76: inb(i_combase+DREG); /* clear any input */ ! 77: inb(i_combase+LSR); ! 78: inb(i_combase+MSR); ! 79: /* set baud rate to 9600 baud */ ! 80: baud = getbaudrate(comport); ! 81: outb(i_combase+LCR, 0x80); ! 82: outb(i_combase+LDLR, baud); ! 83: outb(i_combase+HDLR, baud>>8); ! 84: outb(i_combase+LCR, 3); /* 8 bits, no parity */ ! 85: ! 86: setivec((comport&1)+3, sdintr); ! 87: ! 88: /* set DTR and RTS */ ! 89: /* extra bit (8[4]) is needed to generate interrupts */ ! 90: outb(i_combase+MCR, 15 - ((comport&1) << 2)); ! 91: spl(istate); ! 92: ! 93: /* synthesizer specific initialization sequence here */ ! 94: return; ! 95: } /* on a serial port */ ! 96: ! 97: /* this code not reached */ ! 98: return 1; /* only serial connections implemented */ ! 99: } /* sdsynth_init */ ! 100: ! 101: /* synthesizer appears to be dead */ ! 102: static synth_dead() ! 103: { ! 104: if(!deadbuzz) sdsound(7); ! 105: deadbuzz = 1; ! 106: i_sdc->rdflag = i_sdc->onesymb = 0; ! 107: i_sdc->drain_lbolt = 0; ! 108: } /* synth_dead */ ! 109: ! 110: /* serial port interrupt handler, runs with interrupts off */ ! 111: sdintr() ! 112: { ! 113: char linestat, c; ! 114: short istate; ! 115: ! 116: istate = sphi(); ! 117: inb(i_combase+IIR); ! 118: linestat = inb(i_combase+LSR); ! 119: if(!(linestat & 0x20)) return; ! 120: ! 121: /* if no data to send then reset tx interrupt and return */ ! 122: if(!xmit_ptr) { ! 123: outb(i_combase+IER, 0); ! 124: inxmit = 0; ! 125: } else { ! 126: c = *xmit_ptr++; ! 127: if(!c) c = '\r', xmit_ptr = 0; ! 128: outb(i_combase+DREG, c); ! 129: } ! 130: ! 131: spl(istate); ! 132: } /* sdintr */ ! 133: ! 134: /* return status of synthesizer, ready for more or not. ! 135: * ideally, the unit is ready when it has spoken everything ! 136: * previously sent to it. the Type & Talk has an ! 137: * annoying delay of about 10 seconds between ready indicated ! 138: * and all input spoken. There is nothing I can do ! 139: * about this. Other units, such as the echo, ! 140: * are out of the question, since their delay is measured ! 141: * in minutes. Someday, a speech unit will indicate clearly when ! 142: * it has spoken all input. */ ! 143: sdready() ! 144: { ! 145: char mstat; ! 146: ! 147: /* are we sending a string? */ ! 148: if(inxmit) return 0; ! 149: ! 150: /* a real time delay, after sending return */ ! 151: if(crticks) { --crticks; return 0; } ! 152: ! 153: if(!i_combase) return 1; ! 154: ! 155: if(!sdoverride) { ! 156: /* check to see if votrax is there and ready (DSR and CTS) */ ! 157: mstat = inb(i_combase+MSR); ! 158: if(!(mstat & 0x20)) { ! 159: synth_dead(); ! 160: return 1; ! 161: } ! 162: deadbuzz = 0; ! 163: if(!(mstat & 0x10)) return 0; ! 164: } ! 165: ! 166: return 1; /* ready */ ! 167: } /* sdready */ ! 168: ! 169: /* send text string to the speech synthesizer. ! 170: * routine assumes the text is to be spoken immediately. ! 171: * once the text is spoken, cts will indicate ready for more. */ ! 172: sdtext(s) ! 173: char *s; ! 174: { ! 175: deadbuzz = 0; ! 176: /* is synthesizer dead? */ ! 177: if(!sdoverride && !(inb(i_combase+MSR) & 0x20)) { ! 178: synth_dead(); ! 179: return; ! 180: } ! 181: ! 182: /* set delay, after text is transmitted, so votrax has time to disable cts */ ! 183: crticks = 1; ! 184: xmit_ptr = s; ! 185: inxmit = 1; /* in transmit state */ ! 186: /* enable transmit interrupt */ ! 187: outb(i_combase+IER, 2); ! 188: } /* sdtext */ ! 189: ! 190: /* shut up and discard accumulated text. ! 191: * annoyingly, type & talk must be "ready" for text, ! 192: * before it will honor the shut up command (break on rs232). ! 193: * Be sure the unit is in the ready (cts high) state. */ ! 194: sdshutup() ! 195: { ! 196: char linectrl = inb(i_combase + LCR); ! 197: outb(i_combase+LCR, linectrl|0x40); ! 198: /* Occasionally an interrupt will come along while we are in break. ! 199: * This will cause the break to be a tad longer. ! 200: * The unbelievably picky Votrax unit may not recognize the break, ! 201: * and it may not shut up, or it may perceive ! 202: * a couple extra garbage characters. ! 203: * But long interrupts don't happen very often, ! 204: * and the short ones are potentially important, ! 205: * such as received characters on a serial port. ! 206: * So we wait with interrupts enabled. */ ! 207: sdpause(2560); ! 208: outb(i_combase+LCR, linectrl); ! 209: } /* sdshutup */ ! 210: ! 211: /* given a port address, is it allocated to a speech unit? */ ! 212: sdport_taken(comport) ! 213: { ! 214: int i; ! 215: ! 216: ++comport; ! 217: ! 218: for(i=0; i<4; ++i) ! 219: if((&sd0synth)[i] && comport == (&sd0comport)[i]) ! 220: return 1; ! 221: ! 222: return 0; ! 223: } /* sdport_taken */ ! 224: ! 225: static getbaudrate(comport) ! 226: { ! 227: int baud; ! 228: #ifdef MSDOS ! 229: baud = 12; ! 230: #else ! 231: switch(comport) { ! 232: case 1: baud = albaud[C1BAUD]; break; ! 233: case 2: baud = albaud[C2BAUD]; break; ! 234: case 3: baud = albaud[C3BAUD]; break; ! 235: case 4: baud = albaud[C4BAUD]; break; ! 236: } ! 237: #endif ! 238: return baud; ! 239: } /* getbaudrate */ ! 240:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.