/*********************************************************************
 *                  Flowcode Speech Component Code
 *
 * File: PIC_Speech.c
 *
 * (c) 2009 Matrix Multimedia Ltd.
 * http://www.matrixmultimedia.com
 *
 * Software License Agreement
 *
 * The software supplied herewith by Matrix Multimedia Ltd (the
 * “Company”) for its Flowcode graphical programming language is
 * intended and supplied to you, the Company’s customer, for use
 * solely and exclusively on the Company's products. The software
 * is owned by the Company, and is protected under applicable
 * copyright laws. All rights are reserved. Any use in violation
 * of the foregoing restrictions may subject the user to criminal
 * sanctions under applicable laws, as well as to civil liability
 * for the breach of the terms and conditions of this licence.
 *
 * THIS SOFTWARE IS PROVIDED IN AN “AS IS” CONDITION. NO WARRANTIES,
 * WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED
 * TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 * PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT,
 * IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR
 * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
 *
 * Changelog:
 *
 *  date  | by | description
 * -------+----+-----------------------------------------------------
 * 180309 | BR | Created
 * 130509 | BR | Added % definitions to DefinesCode section
 * 100909 | BR | Added HiTECH compatible definitions
 * 010210 | BR | Fixed a bug where the flash memory address is larger then 16-bit
 ********************************************************************/

/*********************************************************************

 Return & parameter types:
   void
   char
   short
   char*
   float

 Pin directions:
   0 = OUTPUT
   2 = INPUT
   3 = BIDIRECTIONAL

**********************************************************************

[Settings]
CLSID={}
IsAnalogue=0
MultipleAllowed=0
Description=Speech Flowcode Component

**********************************************************************

[Port]
DesiredPort=0
PortMandatory=0
SamePortAsID=0

[Pins]
Count=0

[PinPort]
# PORTA = 0
# PORTB = 1
# PORTC = 2
# PORTD = 3
# PORTE = 4

[PinDesiredBit]

[PinDirection]
# DIR_INPUT = 2
# DIR_OUTPUT = 0
# DIR_BIDIRECTIONAL = 3

[PinMustUsePort]
# boolean

[SamePortAsPinX]
# -1 = any pin
# otherwise, the pin number

[PinMustUsePin]
# boolean

[PinValue]
# boolean (0 = off, 1 = on)

**********************************************************************

[MacroNames]
Count=8
1=GetDefines
2=ReadFlash
3=LookupPhoneme
4=EnableOutput
5=OutputPhoneme
6=ReadByteFromPhoneme
7=ReadPhonemeLength
8=DisableOutput

[MacroReturns]
1=void
2=char
3=void
4=void
5=char
6=char
7=short
8=void

[MacroIsPrivate]
1=1
2=1
3=1
4=0
5=0
6=0
7=0
8=0

[MacroParameters_GetDefines]
Count=0

[MacroParamTypes_GetDefines]


[MacroParameters_ReadFlash]
Count=1
1=address

[MacroParamTypes_ReadFlash]
1=long

[MacroParameters_LookupPhoneme]
Count=1
1=Phoneme

[MacroParamTypes_LookupPhoneme]
1=char*

[MacroParameters_EnableOutput]
Count=0

[MacroParamTypes_EnableOutput]


[MacroParameters_OutputPhoneme]
Count=1
1=Phoneme

[MacroParamTypes_OutputPhoneme]
1=char*

[MacroParameters_ReadByteFromPhoneme]
Count=2
1=Phoneme
2=idx

[MacroParamTypes_ReadByteFromPhoneme]
1=char*
2=short

[MacroParameters_ReadPhonemeLength]
Count=1
1=Phoneme

[MacroParamTypes_ReadPhonemeLength]
1=char*

[MacroParameters_DisableOutput]
Count=0

[MacroParamTypes_DisableOutput]


 ********************************************************************/

/********************************************************************
 * ADDITIONAL CODE
 ********************************************************************/

/*InitialisationCode_Start*/
/*InitialisationCode_End*/

/*InterruptCode_Start*/
/*InterruptCode_End*/

/********************************************************************
 * FUNCTIONS
 ********************************************************************/


void GetDefines()
{
/*Macro_GetDefines_Start*/

}  //Dummy end of function to allow defines to be added correctly


/**** Macro Substitutions ****
a = Stream Audio Tone Control
b = Output Selection
c = TIMER2 Configuration Register Value
d = Capture Compare Configuration Register Value
e = Port Register
f = Data Direction Register
g = Phoneme Data
aa - cg = Starting Address of Phoneme in Memory
******************************/

//Phoneme data
#ifdef _BOOSTC
%g
#endif

#ifdef HI_TECH_C

#asm
%h
#endasm

#endif

//Common Defines

#define MX_SPEECH_PWMCHAN 	%b
#define MX_SPEECH_T2CON		%c
#define MX_SPEECH_CCPxCON	%d
#define MX_SPEECH_PORT  	%e
#define MX_SPEECH_TRIS		%f

short MX_SPEECH_Length = 0;
long MX_SPEECH_Address = 0;

// Dummy function to close the defines section off
void Speech_Dummy_Function();
void Speech_Dummy_Function()
{

/*Macro_GetDefines_End*/
}


char ReadFlash(long address)
{
/*Macro_ReadFlash_Start*/

    char a;

    #ifdef _BOOSTC
    	tblptru = (char) (address >> 16);
		tblptrh = (char) (address >> 8);
		tblptrl = (char) (address & 0xff);

		asm tblrd*+
		asm movf    _tablat,0
		asm movwf    _a
	#endif

	#ifdef HI_TECH_C
		a = flash_read(address);
	#endif

    return a;
/*Macro_ReadFlash_End*/
}



void LookupPhoneme (char* Phoneme, char MSZ_Phoneme)
{
/*Macro_LookupPhoneme_Start*/
	if (FCI_COMPARE ("PA1",3,Phoneme,3,0) == 0)	{MX_SPEECH_Length = 0;	MX_SPEECH_Address = -1; Wdt_Delay_Ms(10); return;}
	if (FCI_COMPARE ("PA2",3,Phoneme,3,0) == 0)	{MX_SPEECH_Length = 0;	MX_SPEECH_Address = -1; Wdt_Delay_Ms(30); return;}
	if (FCI_COMPARE ("PA3",3,Phoneme,3,0) == 0)	{MX_SPEECH_Length = 0;	MX_SPEECH_Address = -1; Wdt_Delay_Ms(50); return;}
	if (FCI_COMPARE ("PA4",3,Phoneme,3,0) == 0)	{MX_SPEECH_Length = 0;	MX_SPEECH_Address = -1; Wdt_Delay_Ms(100); return;}
	if (FCI_COMPARE ("PA5",3,Phoneme,3,0) == 0)	{MX_SPEECH_Length = 0;	MX_SPEECH_Address = -1; Wdt_Delay_Ms(200); return;}
	if (FCI_COMPARE ("OY",2,Phoneme,2,0) == 0)	{MX_SPEECH_Length = 0x08C2;	MX_SPEECH_Address = %aa; return;}
	if (FCI_COMPARE ("AY",2,Phoneme,2,0) == 0)	{MX_SPEECH_Length = 0x0592;	MX_SPEECH_Address = %ab; return;}
	if (FCI_COMPARE ("EH",2,Phoneme,2,0) == 0)	{MX_SPEECH_Length = 0x0256;	MX_SPEECH_Address = %ac; return;}
	if (FCI_COMPARE ("KK",2,Phoneme,2,0) == 0)	{MX_SPEECH_Length = 0x029F;	MX_SPEECH_Address = %ad; return;}
	if (FCI_COMPARE ("PP",2,Phoneme,2,0) == 0)	{MX_SPEECH_Length = 0x04BB;	MX_SPEECH_Address = %ae; return;}
	if (FCI_COMPARE ("JH",2,Phoneme,2,0) == 0)	{MX_SPEECH_Length = 0x037E;	MX_SPEECH_Address = %af; return;}
	if (FCI_COMPARE ("NN",2,Phoneme,2,0) == 0)	{MX_SPEECH_Length = 0x0586;	MX_SPEECH_Address = %ag; return;}
	if (FCI_COMPARE ("IH",2,Phoneme,2,0) == 0)	{MX_SPEECH_Length = 0x01E9;	MX_SPEECH_Address = %ah; return;}
	if (FCI_COMPARE ("TT2",3,Phoneme,3,0) == 0) {MX_SPEECH_Length = 0x030B;	MX_SPEECH_Address = %ai; return;}
	if (FCI_COMPARE ("RR1",3,Phoneme,3,0) == 0)	{MX_SPEECH_Length = 0x0527;	MX_SPEECH_Address = %aj; return;}
	if (FCI_COMPARE ("AX",2,Phoneme,2,0) == 0)	{MX_SPEECH_Length = 0x028D;	MX_SPEECH_Address = %ak; return;}
	if (FCI_COMPARE ("MM",2,Phoneme,2,0) == 0)	{MX_SPEECH_Length = 0x05A1;	MX_SPEECH_Address = %al; return;}
	if (FCI_COMPARE ("TT1",3,Phoneme,3,0) == 0)	{MX_SPEECH_Length = 0x02A8;	MX_SPEECH_Address = %am; return;}
	if (FCI_COMPARE ("DH",2,Phoneme,2,0) == 0)	{MX_SPEECH_Length = 0x047E;	MX_SPEECH_Address = %an; return;}
	if (FCI_COMPARE ("IY",2,Phoneme,2,0) == 0)	{MX_SPEECH_Length = 0x058D;	MX_SPEECH_Address = %ao; return;}
	if (FCI_COMPARE ("EY",2,Phoneme,2,0) == 0)	{MX_SPEECH_Length = 0x0659;	MX_SPEECH_Address = %ap; return;}
	if (FCI_COMPARE ("DD1",3,Phoneme,3,0) == 0)	{MX_SPEECH_Length = 0x01A4;	MX_SPEECH_Address = %aq; return;}
	if (FCI_COMPARE ("UW1",3,Phoneme,3,0) == 0)	{MX_SPEECH_Length = 0x02DA;	MX_SPEECH_Address = %ar; return;}
	if (FCI_COMPARE ("AO",2,Phoneme,2,0) == 0)	{MX_SPEECH_Length = 0x0385;	MX_SPEECH_Address = %as; return;}
	if (FCI_COMPARE ("AA",2,Phoneme,2,0) == 0)	{MX_SPEECH_Length = 0x0324; MX_SPEECH_Address = %at; return;}
	if (FCI_COMPARE ("YY2",3,Phoneme,3,0) == 0)	{MX_SPEECH_Length = 0x0473; MX_SPEECH_Address = %au; return;}
	if (FCI_COMPARE ("AE",2,Phoneme,2,0) == 0)	{MX_SPEECH_Length = 0x0361;	MX_SPEECH_Address = %av; return;}
	if (FCI_COMPARE ("HH1",3,Phoneme,3,0) == 0)	{MX_SPEECH_Length = 0x0300;	MX_SPEECH_Address = %aw; return;}
	if (FCI_COMPARE ("BB1",3,Phoneme,3,0) == 0)	{MX_SPEECH_Length = 0x0178;	MX_SPEECH_Address = %ax; return;}
	if (FCI_COMPARE ("TH",2,Phoneme,2,0) == 0)	{MX_SPEECH_Length = 0x0419;	MX_SPEECH_Address = %ay; return;}
	if (FCI_COMPARE ("UH",2,Phoneme,2,0) == 0)	{MX_SPEECH_Length = 0x02F4;	MX_SPEECH_Address = %az; return;}
	if (FCI_COMPARE ("UW2",3,Phoneme,3,0) == 0) {MX_SPEECH_Length = 0x054D;	MX_SPEECH_Address = %ba; return;}
	if (FCI_COMPARE ("AW",2,Phoneme,2,0) == 0)	{MX_SPEECH_Length = 0x07C7;	MX_SPEECH_Address = %bb; return;}
	if (FCI_COMPARE ("DD2",3,Phoneme,3,0) == 0)	{MX_SPEECH_Length = 0x0297;	MX_SPEECH_Address = %bc; return;}
	if (FCI_COMPARE ("GG3",3,Phoneme,3,0) == 0)	{MX_SPEECH_Length = 0x0398;	MX_SPEECH_Address = %bd; return;}
	if (FCI_COMPARE ("VV",2,Phoneme,2,0) == 0)	{MX_SPEECH_Length = 0x03EB;	MX_SPEECH_Address = %be; return;}
	if (FCI_COMPARE ("GG1",3,Phoneme,3,0) == 0)	{MX_SPEECH_Length = 0x0264;	MX_SPEECH_Address = %bf; return;}
	if (FCI_COMPARE ("SH",2,Phoneme,2,0) == 0)	{MX_SPEECH_Length = 0x0639;	MX_SPEECH_Address = %bg; return;}
	if (FCI_COMPARE ("ZH",2,Phoneme,2,0) == 0)  {MX_SPEECH_Length = 0x0479;	MX_SPEECH_Address = %bh; return;}
	if (FCI_COMPARE ("RR2",3,Phoneme,3,0) == 0) {MX_SPEECH_Length = 0x03DA;	MX_SPEECH_Address = %bi; return;}
	if (FCI_COMPARE ("FF",2,Phoneme,2,0) == 0)	{MX_SPEECH_Length = 0x0394;	MX_SPEECH_Address = %bj; return;}
	if (FCI_COMPARE ("KK2",3,Phoneme,3,0) == 0) {MX_SPEECH_Length = 0x0459; MX_SPEECH_Address = %bk; return;}
	if (FCI_COMPARE ("KK1",3,Phoneme,3,0) == 0)	{MX_SPEECH_Length = 0x03E6;	MX_SPEECH_Address = %bl; return;}
	if (FCI_COMPARE ("ZZ",2,Phoneme,2,0) == 0)  {MX_SPEECH_Length = 0x04BD;	MX_SPEECH_Address = %bm; return;}
	if (FCI_COMPARE ("NG",2,Phoneme,2,0) == 0)  {MX_SPEECH_Length = 0x0627;	MX_SPEECH_Address = %bn; return;}
	if (FCI_COMPARE ("LL",2,Phoneme,2,0) == 0)	{MX_SPEECH_Length = 0x2D5; 	MX_SPEECH_Address = %bo; return;}
	if (FCI_COMPARE ("WW",2,Phoneme,2,0) == 0)	{MX_SPEECH_Length = 0x047C;	MX_SPEECH_Address = %bp; return;}
	if (FCI_COMPARE ("XR",2,Phoneme,2,0) == 0)  {MX_SPEECH_Length = 0x0782;	MX_SPEECH_Address = %bq; return;}
	if (FCI_COMPARE ("WH",2,Phoneme,2,0) == 0)	{MX_SPEECH_Length = 0x053D;	MX_SPEECH_Address = %br; return;}
	if (FCI_COMPARE ("YY1",3,Phoneme,3,0) == 0)	{MX_SPEECH_Length = 0x02F4;	MX_SPEECH_Address = %bs; return;}
	if (FCI_COMPARE ("CH",2,Phoneme,2,0) == 0)	{MX_SPEECH_Length = 0x04AA;	MX_SPEECH_Address = %bt; return;}
	if (FCI_COMPARE ("ER1",3,Phoneme,3,0) == 0)	{MX_SPEECH_Length = 0x03D6;	MX_SPEECH_Address = %bu; return;}
	if (FCI_COMPARE ("ER2",3,Phoneme,3,0) == 0)	{MX_SPEECH_Length = 0x067C; MX_SPEECH_Address = %bv; return;}
	if (FCI_COMPARE ("OW",2,Phoneme,2,0) == 0)	{MX_SPEECH_Length = 0x054D;	MX_SPEECH_Address = %bw; return;}
	if (FCI_COMPARE ("DH2",3,Phoneme,3,0) == 0)	{MX_SPEECH_Length = 0x0582;	MX_SPEECH_Address = %bx; return;}
	if (FCI_COMPARE ("SS",2,Phoneme,2,0) == 0)	{MX_SPEECH_Length = 0x022A;	MX_SPEECH_Address = %by; return;}
	if (FCI_COMPARE ("NN2",3,Phoneme,3,0) == 0)	{MX_SPEECH_Length = 0x0492;	MX_SPEECH_Address = %bz; return;}
	if (FCI_COMPARE ("HH2",3,Phoneme,3,0) == 0)	{MX_SPEECH_Length = 0x03E7;	MX_SPEECH_Address = %ca; return;}
	if (FCI_COMPARE ("OR",2,Phoneme,2,0) == 0)	{MX_SPEECH_Length = 0x0747;	MX_SPEECH_Address = %cb; return;}
	if (FCI_COMPARE ("AR",2,Phoneme,2,0) == 0)	{MX_SPEECH_Length = 0x0641;	MX_SPEECH_Address = %cc; return;}
	if (FCI_COMPARE ("YR",2,Phoneme,2,0) == 0)	{MX_SPEECH_Length = 0x078D;	MX_SPEECH_Address = %cd; return;}
	if (FCI_COMPARE ("GG2",3,Phoneme,3,0) == 0)	{MX_SPEECH_Length = 0x024B;	MX_SPEECH_Address = %ce; return;}
	if (FCI_COMPARE ("EL",2,Phoneme,2,0) == 0)	{MX_SPEECH_Length = 0x0440;	MX_SPEECH_Address = %cf; return;}
	if (FCI_COMPARE ("BB2",3,Phoneme,3,0) == 0)	{MX_SPEECH_Length = 0x023B;	MX_SPEECH_Address = %cg; return;}
	else {MX_SPEECH_Length = 0;	MX_SPEECH_Address = -1; return;}
/*Macro_LookupPhoneme_End*/
}



void EnableOutput()
{
/*Macro_EnableOutput_Start*/
	#if (MX_SPEECH_PWMCHAN == 0)
		MX_SPEECH_PORT = 0x7F;
		MX_SPEECH_TRIS = 0x00;
	#endif

	#if (MX_SPEECH_PWMCHAN == 1)
		pr2 = 255;
	    t2con = MX_SPEECH_T2CON;
	    ccp1con = MX_SPEECH_CCPxCON;
	    clear_bit(MX_PWM_TRIS1, MX_PWM_1);
	#endif

	#if (MX_SPEECH_PWMCHAN == 2)
		pr2 = 255;
	    t2con = MX_SPEECH_T2CON;
		ccp2con = MX_SPEECH_CCPxCON;
		clear_bit(MX_PWM_TRIS2, MX_PWM_2);
	#endif
/*Macro_EnableOutput_End*/
}



char OutputPhoneme (char* Phoneme, char MSZ_Phoneme)
{
/*Macro_OutputPhoneme_Start*/
	short idx, temp;
	char output;

	LookupPhoneme(Phoneme, MSZ_Phoneme);

	if(MX_SPEECH_Address == -1)
		return(255);

	for (idx = 0; idx < MX_SPEECH_Length; idx++)
	{
		temp = idx + MX_SPEECH_Address;
		output = ReadFlash(temp);

		#if (MX_SPEECH_PWMCHAN == 0)
			MX_SPEECH_PORT = output;
		#endif

		#if (MX_SPEECH_PWMCHAN == 1)
			ccpr1l = output;
		#endif

		#if (MX_SPEECH_PWMCHAN == 2)
			ccpr2l = output;
		#endif

		delay_10us(%a);
	}
	return(0);
/*Macro_OutputPhoneme_End*/
}



char ReadByteFromPhoneme (char* Phoneme, char MSZ_Phoneme, short idx)
{
/*Macro_ReadByteFromPhoneme_Start*/
	long temp;
	LookupPhoneme(Phoneme, MSZ_Phoneme);

	if(MX_SPEECH_Address == -1)
		return 0;

	if(idx < MX_SPEECH_Length)
	{
		temp = idx + MX_SPEECH_Address;
		return ReadFlash(temp);
	}
	return 0;
/*Macro_ReadByteFromPhoneme_End*/
}



short ReadPhonemeLength (char* Phoneme, char MSZ_Phoneme)
{
/*Macro_ReadPhonemeLength_Start*/
	LookupPhoneme(Phoneme, MSZ_Phoneme);
	if(MX_SPEECH_Address == -1)
		return 0;
	return MX_SPEECH_Length;
/*Macro_ReadPhonemeLength_End*/
}



void DisableOutput()
{
/*Macro_DisableOutput_Start*/
	#if (MX_SPEECH_PWMCHAN == 0)
		MX_SPEECH_TRIS = 0xFF;
	#endif

	#if (MX_SPEECH_PWMCHAN == 1)
		ccp1con = 0x00;
	#endif

	#if (MX_SPEECH_PWMCHAN == 2)
		ccp2con = 0x00;
	#endif
/*Macro_DisableOutput_End*/
}