/*                            PROGRAM SPEECH
			Code conversion by Eugene Klein

  Produce speech using General Instrument's SPO256 Speech Processor.  The
  chip has 64 address locations each identifying instructions for sounding
  an allophone.  The chip's output should be fed to an audio amplifier.
*/

#include 
#include 
#include 
#include 
#include 
#include 
#include "My_TPU.h"


/*
    NOTE: The pound sign, "#", in front of a number, tells the Turbo
	  Pascal compiler that the number is an ASCII value to be
	  assigned to the character variable in front of the equal sign.

 Allophone information based on General Instruments' Data Sheets,
 and Radio Shack Data sheet packaged with item 276-1784.


      DATA SHEET     DICTIONARY
      ALLOPHONE     PRONUNCIATION
       SYMBOL          SYMBOL                 NOTES
*/

#define AA    24     //   Д
#define AE    26     //   a
#define AO    23     //   Г
#define AR    59     //   Дr
#define AW    32     //   ou
#define AX    15     //   u
#define AY    6      //   Н
#define BB1   28     //   b   final position
			//   b   between vowels, or in clusters
#define BB2   63     //   b   initial position before a vowel
#define CH    50     //   ch
#define DD1   21     //   d   final position
#define DD2   33     //   d   initial positin
#define DH1   18     //  th   word's initial position
#define DH2   54     //  th   word's final position
			//  th   between vowels
#define EH    7      //   e
#define EL    62     //   l
#define ER1   51     //   ar
#define ER2   52     //   ur
#define EY    20     //   Е
#define FF    40     //        silent, use singly in final position
#define GG1   36     //   g    before high front vowels: ir, К, i, Е, e, er
#define GG2   61     //   g    before high back vowels: ХХ, oo, Х, oi, u
			//   g    before clusters
#define GG3   34     //   g    before low vowels: a, ou, Н, Дr, Д, Г, Уr, ar, ur

			//        medical clusters
			//   g    final position
#define HH1   27     //   h    before front vowels: ir, К, i, К, e, er, a
#define HH2   57     //   h    before back vowels: ХХ, oo, Х, oi, Г, Уr, Дr
#define IH    12     //   i
#define IY    19     //   К
#define JH    10     //   j
#define KK1   42     //   k    before front vowels
			//   ir, К, i, Е, e, er, Н, a, ar, ur, u
			//   k    initial clusters
#define KK2   41     //   k    final position
#define KK3   8      //   k    before back vowel:ХХ, oo, Х, oi, Уr, Дr, Г
#define LL    45     //   L
#define MM    16     //   m
#define NG    44     //   ng
#define NN1   11     //   n    before front and central vowels:
			//   ir, К, i, Е, e, er, a, ar, ur, u, ou, Н, Х
			//   n    final clusters
#define NN2   56     //   n    before back vowels: oo, Х, oi, Уr, Дr, Г
#define ORR   58     //   Уr
#define OW    53     //   Х
#define OY    5      //   oi
#define PP1   9      //   P
#define RR1   14     //  _R    initial position   beginning of word
#define RR2   39     //   r    initial cluster
#define SH    37     //   sh
#define SS    55     // silent
#define TH    29     // silent
#define TT1   17     //   t     final cluster before SS
#define TT2   13     //   t     all other positions
#define UH    30     //   oo
#define UW1   22     //   ХХ    after y
#define UW2   31     //   ХХ    in one syllable words
#define VV    35     //   V
#define WH    48     //   hW
#define WW    46     //   W
#define XR    47     //   er
#define YR    60     //   ir
#define YY1   49     //   y     clusters
#define YY2   25     //   Y     initial position
#define ZH    38     //   Zh
#define ZZ    43     //   z

#define PA1  0 // pause 10 ms, before BB, DD, GG, and JH
#define PA2  1 // pause 30 ms, before BB, DD, GG, and JH
#define PA3  2 // pause 50 ms, before PP, TT, KK, and CH, and between words
#define PA4  3 // pause 100 ms, between clauses and sentences
#define PA5  4 // pause 200 ms, between clauses and sentences

      // allophones proceeded by "", can be doubled

unsigned  char E;
unsigned int Lpt_Num, Lpt_Port_Address;

void Speak(char *Phrase,int Size)
{
/*
  Transmit each allophone byte of phrase to SPO256.
  Procedure will only transmit to LPT1.
  Similar to using BASIC'S LPRINT, or Pascal's WRITE commands
*/

 unsigned char N;

 for(N=0;N<Size;N++)
 {
     putc(Phrase[N],stdprn);
  delay(30);                             // put data on data lines
 }
}

void Say(char *Phrase,int Size)
{
/*
  Transmit each allophone byte of phrase to SPO256.
  Will transmit on LPT1, LPT2, or LPT3.
*/
 const int D7 = 128;
 unsigned char N, Temp;

 for(N=0;N<Size;N++)
 {
 /*  Check speech chip's standby line, LRQ, ( D7, at pin 10 on printer port
     When LRQ is logic high, chip can accept new data.
 */
  while(( inport(Lpt_Port_Address + 1) & D7 ) == 0); // ok to transmit?
  {
/* D0 set HIGH = 0. Why? Because you have to account for inverteed logic
   All four control lines, at LPT Port Address + 2, are set to inactive
     logic levels by sending 10, binary 00001010.
   Remember, Storbe line is inverted. High is 0, Low is 1.
*/
   outport(Lpt_Port_Address + 2,10);         // set all control bits to inactive
   outport(Lpt_Port_Address,Phrase[N]);      // put data on data lines
   outport(Lpt_Port_Address + 2,11);         // set strobe, D0, to active LOW
   outport(Lpt_Port_Address + 2,10);          // set strobe, D0, to inactive HIGH
  }
 }
}

void main()
{
 // define words by allophone sounds
 char Computer[]= {KK1,AX,PA1,MM,PP1,YY1,UW1,TT2,ER1,PA3};
 char  Talking[]= {TT2,AO,AO,PA3,KK1,IH,NG,PA3};
 char Hello[]= {HH1,EH,LL,AX,OW,PA5};

 // transmit speech allophones via LPT1

 Speak(Computer,sizeof(Computer));
 Speak(Talking,sizeof(Talking));
 delay(250);
 Speak(Hello,sizeof(Hello));

 // alternete method of sending speech allophones to LPT1, LPT2, or LPT3
 Lpt_Num = Select_Printer_Port();
 Lpt_Port_Address = Init_Printer_Port(Lpt_Num);
 Say(Computer,sizeof(Computer));
 Say(Talking,sizeof(Talking));
 delay(250);
 Say(Hello,sizeof(Hello));
}