Stand Alone mBed OS Text To Speech Click Board Example

Fork of Hexi_Click_Relay-v3_Example by Hexiwear

main.cpp

Committer:
daveyclk
Date:
2016-10-26
Revision:
2:84ca2f63ecdf
Parent:
1:070fc531e5cb

File content as of revision 2:84ca2f63ecdf:

/****************************************************************************
* Title                 :   Hexiware Text To Speech Click
* Filename              :   Hexi_talking_one_main
* Author                :   Dave Clarke
* Origin Date           :   26/10/2016
* Notes                 :   mBed OS Text to Speech Click Interface (rough) 
*****************************************************************************/
/**************************CHANGE LIST **************************************
*
*    Date    Software Version    Initials       Description
*  26/10/16       1.0.0            DC        Interface Created.
*
*****************************************************************************/

/**
 * @page TEST_CFG Test Configurations
 * <h3> Test configuration : </h3>
 * @par
 * <ul>
 * <li><b> MCU           </b> :      MK64FN1M0XXX12               </li>
 * <li><b> Dev. Board    </b> :      HEXIWEAR                     </li>
 * <li><b> Oscillator    </b> :      12 MHz external              </li>
 * <li><b> Ext. Modules  </b> :      none                         </li>
 * <li><b> Ext. Modules  </b> :      TTS Click on mikroBUS 2      </li>
 * <li><b> SW            </b> :      mBed OS5    </li>
 * </ul>
 */

/**
 * @mainpage
 * <h3> Text To Speech with HEXIWEAR and mBed OS 5 </h3>
 * @par Using mBed)S and a Hexiware you can now use the Text To Speech Click Board
 * 
 * 
 * 
 
 * <h3> Speech Features </h3>
 * @par Text to Speech Click, Hexiwear docking station, Hexiware
 */

/******************************************************************************
* Includes
*******************************************************************************/

#include "mbed.h"
#include "text_to_speech.h"
#include "text_to_speech_hal.h"
#include "text_to_speech_hw.h"
#include "text_to_speech_img.h"
#include "string.h"
#include <stdbool.h>
#include <stdlib.h>




/******************************************************************************
* Module Variable Definitions
*******************************************************************************/
/* Indication Flags */
static volatile bool        _tts_rdy_f;
static volatile bool        _spc_rdy_f;
static volatile bool        _tts_fin_f;
static volatile bool        _spc_fin_f;
/* Error Buffers */
static uint16_t             _req_err;
static uint16_t             _err_code;
/* Default Configuration */
static ACONF_t              _audio_conf;
static TTSCONF_t            _tts_conf;
static PMANCONF_t           _pman_conf;

static bool                 _flush_enable;
/* Timer flag and counter */
static volatile bool        _ticker_f;
static volatile uint16_t    _ticker;
/* Input and output buffers */
static  ISC_REQ_t   _last_req;
static  ISC_RESP_t  _last_rsp;
 /* Text Buffer */ 
char text[20];
static uint8_t test[ 8 ] = { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
int frequency = 750000;
VER_t *version;
/******************************************************************************
* Function Prototypes
*******************************************************************************/
/* Checks for indications */
static int _parse_ind( void );
/* Message block and error callback function pointers */
static void ( *_fatal_err_callback )( uint16_t *err_code );
static void ( *_err_callback )( uint16_t *err_code );
static void ( *_msg_block_callback )( uint16_t *msg_code,
                                      uint16_t *err_code ); 


/* Instantiate the Click Text to Speech pinout */ 
DigitalOut TTS_RST(PTB19);
DigitalOut TTS_CS(PTC3);
DigitalOut TTS_MUTE(PTB3);
DigitalIn  TTS_RDY(PTB8);
      
//Instantiate SPI for comms with Speak module
SPI TextToSpeech(PTC6, PTC7, PTC5); // MOSI, MISO, SCK


// Debug Serial
Serial pc(USBTX, USBRX);

void SysInit(void)
{
    tts_hal_cs_high();
    TextToSpeech.format(8,3);
    TextToSpeech.frequency(frequency);
   
    
}

void fatal_err( uint16_t *err );
void msg_blk( uint16_t *req, uint16_t *err );

int main() 
{
    
    SysInit();
    pc.printf("System Init Done!\r\n");
    tts_init();
    pc.printf("tts Init Done!\r\n");
    tts_setup();
    pc.printf("tts setup Done!\r\n");
    tts_msg_block_callback( msg_blk );
    tts_fatal_err_callback( fatal_err );
    tts_config( 0x01, false, TTSV_US, 0x0090 );
    //tts_mute();
    //tts_speak( "[:nw][:dv ap 195 pr 80]" );
    //tts_speak( "[:np][:dv ap 100 pr 50]" );
    //tts_speak( "[:nw]" );
    //wait( 2 );
    //tts_unmute();
     
    while(1)
    {
       /* frozen
         verse one
        tts_speak( "The snow glows white on the mountain tonight, Not a footprint to be seen. " );
        wait(0.1);
        tts_speak( "A kingdom of isolation, and it looks like I'm the Queen.  " );
        wait(0.1);
        tts_speak( "The wind is howling like this swirling storm inside. " );
        wait(0.1);
        tts_speak( "Couldn't keep it in. " );
        wait(0.1);
        tts_speak( "Heaven knows I've tried. " );
        wait(0.1);
        tts_speak( "Don't let them in, don't let them see.  " );
        wait(0.1);
        tts_speak( "Be the good girl you always have to be. " );
        wait(0.1);
        tts_speak( "Conceal, don't feel, don't let them know. " );
        wait(0.1);
        tts_speak( "Well now they know. " );
        wait(0.1);
        
         chorus one
        tts_speak( "Let it go, let it go.  " );
        wait(0.1);
        tts_speak( "Can't hold it back anymore. " );
        wait(0.1);
        tts_speak( "I don't care " );
        wait(0.1);
        tts_speak( "what they're going to say" );
        wait(0.1);  
        tts_speak( "Let the storm rage on." );
        wait(0.1);
        tts_speak( "The cold never bothered me anyway" );
        wait(0.1);
        
         verse two
        tts_speak( "It's funny how some distance " );
        wait(0.1);
        tts_speak( "Makes everything seem small  " );
        wait(0.1);
        tts_speak( "And the fears that once controlled me " );
        wait(0.1);
        tts_speak( "Can't get to me at all " );
        wait(0.1);
        tts_speak( "It's time to see what I can do " );
        wait(0.1);
        tts_speak( "To test the limits and break through" );
        wait(0.1);
        tts_speak( "No right, no wrong, no rules for me, " );
        wait(0.1);
        tts_speak( "I'm free! " );
        wait(0.1);
        
        chorus two
        tts_speak( "Let it go, let it go.  " );
        wait(0.1);
        tts_speak( "I am one with the wind and sky " );
        wait(0.1);
        tts_speak( "Let it go, let it go " );
        wait(0.1);
        tts_speak( "You'll never see me cry" );
        wait(0.1);  
        tts_speak( "Here I stand" );
        wait(0.1);
        tts_speak( "And here I'll stay" );
        wait(0.1);
        tts_speak( "Let the storm rage on" );
        wait(0.1);
        
        middle eight
        tts_speak( "My power flurries through the air into the ground " );
        wait(0.1);
        tts_speak( "My soul is spiraling in frozen fractals all around " );
        wait(0.1);
        tts_speak( "And one thought crystallizes like an icy blast " );
        wait(0.1);
        tts_speak( "I'm never going back, the past is in the past" );
        wait(0.1);
         
        last chorus
        tts_speak( "Let it go, let it go" );
        wait(0.1);
        tts_speak( "And I'll rise like the break of dawn" );
        wait(0.1);
        tts_speak( "Let it go, let it go" );
        wait(0.1);        
        tts_speak( "That perfect girl is gone" );
        wait(0.1);
        tts_speak( "Here I stand" );
        wait(0.1);
        tts_speak( "In the light of day" );
        wait(0.1);
        tts_speak( "Let the storm rage on" );
        wait(0.5);
        tts_speak( "The cold never bothered me anyway" );
        wait(1);
        */
        
        // keep talking
        tts_speak( "For millions of years mankind lived just like the animals." );
        wait(0.5);        
        tts_speak( "Then something happenend which unleashed the power of our imagination" );
        wait(0.5);
        tts_speak( "We learned to talk" );
        wait(10);
                                            
   }
}

void msg_blk( uint16_t *req, uint16_t *err )
{
    char txt[ 6 ];
    
    pc.printf( " MSG BLOCKED \r\n" );
    sprintf( txt, "%x\r\n", *req );
    pc.printf( txt );
    sprintf( txt, "%x\r\n", *err );
    pc.printf( txt );
}

void fatal_err( uint16_t *err )
{
    pc.printf( "Fatal Error Detected" );
    tts_init();
    tts_fatal_err_callback( fatal_err );
}


///////////////////text_to_speech_hal.c///////////////
void tts_hal_cs_high()
{
    
    TTS_CS = 1;
}

void tts_hal_cs_low()
{
    TTS_CS = 0;
    
}

void tts_hal_mut_high()
{
    TTS_MUTE = 1;
}

void tts_hal_mut_low()
{
    TTS_MUTE = 0;
}
/*
void tts_hal_reset( void )
{
    TTS_RST = 0;
    wait(0.01);
    TTS_RST = 1;
    //wait(1);
    wait(POR_TIME / 1000);
}
*/
void tts_hal_reset( void )
{
    tts_hal_cs_high();
    TTS_RST = 0;
    tts_hal_write_pad(1);
    wait(0.01);
    TTS_RST = 1;
    wait(POR_TIME);
}
bool tts_hal_msg_rdy( void )
{
    return TTS_RDY;
}

void tts_hal_init()
{
    tts_hal_reset();
    tts_hal_cs_high();
    tts_hal_mut_low();
}


void tts_hal_write( uint8_t *buffer,
                    uint16_t count, bool boot )
{
 
    while( count-- )
    {
        if(!boot)
            pc.printf("%02X\r\n", *buffer);
        
        TextToSpeech.write( *buffer++  );
        
     }   
}

void tts_hal_write_pad( int cnt )
{
   
    tts_hal_cs_low();
    while(cnt--)
    {
         TextToSpeech.write( PADDING_BYTE );
    }  

    tts_hal_cs_high();
}

void tts_hal_read( uint8_t *buffer,
                   uint16_t count )
{

    while(count--)
    {   
        *buffer++ = TextToSpeech.write( DUMMY_BYTE ); //read spi bus
      
       
        //pc.printf("buffer = %X\n\r", *buffer);
    }
}

////////////////text_to_speech.c///////////////////////////////

static int _parse_ind( void )
{
    uint16_t rsp_idx = tts_rsp_idx();
    if ( rsp_idx == ISC_MSG_BLOCKED_RESP )
    {
        uint8_t rsp_data[ 4 ] = { 0 };

        _req_err = 0;
        _err_code = 0;

        tts_rsp_data( rsp_data );

        _req_err |= rsp_data[ 0 ];
        _req_err |= rsp_data[ 1 ] << 8;
        _err_code |= rsp_data[ 2 ];
        _err_code |= rsp_data[ 3 ] << 8;

        if( _msg_block_callback != NULL )
            _msg_block_callback( &_req_err, &_err_code );

        return 1;

    } else if ( rsp_idx == ISC_ERROR_IND ) {

         uint8_t rsp_data[ 4 ] = { 0 };

        _req_err = 0;
        _err_code = 0;

        tts_rsp_data( rsp_data );

        _err_code |= rsp_data[ 0 ];
        _err_code |= rsp_data[ 1 ] << 8;

        if ( _err_code && _err_code < 0x8000 )
        {
            if( _err_callback != NULL )
                _err_callback( &_err_code );

        } else if ( _err_code && _err_code > 0x7FFF ) {

            if( _fatal_err_callback != NULL )
                _fatal_err_callback( &_err_code );
        }

        return 1;

    } else if ( rsp_idx == ISC_TTS_READY_IND ) {

        _tts_rdy_f = 1;

    } else if ( rsp_idx == ISC_SPCODEC_READY_IND ) {

        _spc_rdy_f = 1;

    } else if ( rsp_idx == ISC_TTS_FINISHED_IND ) {

        _tts_fin_f = 1;

    } else if ( rsp_idx == ISC_SPCODEC_FINISHED_IND ) {

        _spc_fin_f = 1;
    }

    return 0;
}
/******************************************************************************
* Public Function Definitions
*******************************************************************************/


void tts_init()
{
    _req_err = 0;
    _err_code = 0;

    _tts_rdy_f = true;
    _spc_rdy_f = true;
    _tts_fin_f = true;
    _spc_fin_f = true;

    _audio_conf.as = 0x00;
    _audio_conf.ag = 0x43;
    _audio_conf.amp = 0x00;
    _audio_conf.asr = ASR_11KHZ;
    _audio_conf.ar = 0x00;
    _audio_conf.atc = 0x00;
    _audio_conf.acs = 0x00;
    _audio_conf.dc = 0x00;

    _tts_conf.sr = 0x01;
    _tts_conf.voice = 0x00;
    _tts_conf.ep = 0x00;
    _tts_conf.lang = TTSV_US;
    _tts_conf.sr_wpm_lsb = 0xc8;
    _tts_conf.sr_wpm_msb = 0x00;
    _tts_conf.ds = 0x00;
    _tts_conf.res = 0x00;

    _pman_conf.am_lsb = 0x01;
    _pman_conf.am_msb = 0x00;
    _pman_conf.spi_clk = 0x01;
    _pman_conf.pad = PADDING_BYTE;

    _flush_enable = false;

    _msg_block_callback = NULL;
    _fatal_err_callback = NULL;
    _err_callback = NULL;

    tts_hw_init();
}

void tts_msg_block_callback( void( *msg_blk_ptr )( uint16_t *req_ptr,
                                                   uint16_t *err_ptr ) )
{
    _msg_block_callback = msg_blk_ptr;
}

void tts_fatal_err_callback( void( *fatal_err_ptr )( uint16_t *err_ptr ) )
{
    _fatal_err_callback = fatal_err_ptr;
}

void tts_err_callback( void( *error_ptr )( uint16_t *err_ptr ) )
{
    _err_callback = error_ptr;
}

void tts_mute()
{
    tts_mute_cmd( true );
}

void tts_unmute()
{
    tts_mute_cmd( false );
}


void tts_setup()
{
 
   
  
   // pc.printf( "tts init data size: %i\n\r", sizeof(TTS_INIT_DATA2));
   
    tts_version_boot(); 
    int succ = tts_image_load( (uint8_t*)TTS_INIT_DATA, sizeof( TTS_INIT_DATA ) );
   
    if ( succ != 0x0001 )
    {
            pc.printf("tts init data failed!\n\r");
            pc.printf("returned value: %04X\n\r", succ);
            wait(100);
    }        
    pc.printf("tts image load done\n\r"); //executes OK
    succ =  tts_image_exec(); // executes ok
    
    if ( succ != 0x0001 )
    {
        pc.printf("tts image exec failed!\n\r");
        pc.printf("returned value: %04X\n\r", succ);
        wait(100);
    } 
    pc.printf("tts image exec done\n\r");
    tts_interface_test();
    pc.printf("tts interface test done\n\r");
    tts_power_default_config();
    pc.printf("tts power default done\n\r");
    tts_audio_default_config();
    pc.printf("tts audio default done\n\r");
    tts_volume_set( 0 );
    pc.printf("tts volume set done\n\r");
    tts_default_config();
    pc.printf("tts default config done\n\r");
}

void tts_version_boot( void )
{
    
    uint8_t tmp_resp[ 16 ] = { 0 };

    wait( RESET_TO_BOOT_TIME );
    
    
    tts_parse_req( ISC_VERSION_REQ_BOOT, NULL, 0 );
    
    
    while( !tts_rsp_chk( ISC_VERSION_RESP_BOOT ) )
    {
        tts_get_resp();

    }
    tts_hal_write_pad( 16);
    tts_rsp_data( tmp_resp );
    pc.printf("hwver0 %X \n\r", tmp_resp[ 0 ]);
    pc.printf("hwver1 %X \n\r", tmp_resp[ 1 ]);
}



uint16_t tts_image_load(const uint8_t *image,
                         uint16_t count )
{
  
    uint16_t tmp_resp = 0;
    uint16_t index = 0;
    uint8_t raw_resp[ 2 ] = { 0 };
   
    while ( ( count - index ) > ( BOOT_MESSAGE_MAX - 4  ) )
    {
       
       tts_parse_boot_img( image + index, BOOT_MESSAGE_MAX - 4  );
       wait(0.01);
       index += ( BOOT_MESSAGE_MAX - 4 );
    }
    tts_parse_boot_img( image + index, count - index );
    wait(0.01);           
    
    while( !tts_rsp_chk( ISC_BOOT_LOAD_RESP ) )
    {
        tts_get_resp();
          
        if( _parse_ind() )
            return _err_code;
    }
    tts_rsp_data( raw_resp );

    tmp_resp |= raw_resp[ 0 ];
    tmp_resp |= raw_resp[ 1 ] << 8;
  
    return tmp_resp;
    //return ( tmp_resp == 1 ) ?  tmp_resp : 0x0000;
}

uint16_t tts_image_exec()
{
    uint16_t tmp_resp = 0;
    uint8_t raw_resp[ 2 ] = { 0 };
   
    
    tts_parse_req( ISC_BOOT_RUN_REQ, NULL, 0 );
    
    
    
      
    while( !tts_rsp_chk( ISC_BOOT_RUN_RESP ) )
    {
        
        tts_get_resp();
       
        if( _parse_ind() )
            return _err_code;
    }
    tts_rsp_data( raw_resp );

    tmp_resp |= raw_resp[ 0 ];
    tmp_resp |= raw_resp[ 1 ] << 8;

    return  tmp_resp;
}

uint16_t tts_interface_test()
{
    uint16_t tmp_resp = 0;
    uint8_t raw_resp[ 2 ] = { 0 };
    
    
    wait( BOOT_TO_MAIN_MODE );
    
    tts_parse_req( ISC_TEST_REQ, test, 8 );
           
    while( !tts_rsp_chk( ISC_TEST_RESP ) )
    {
        tts_get_resp();
      
        if( _parse_ind() )
            return _err_code;
    }

    tts_rsp_data( raw_resp );

    tmp_resp |= raw_resp[ 0 ];
    tmp_resp |= raw_resp[ 1 ] << 8;

    return tmp_resp;
}

 uint16_t tts_version_main( VER_t *buffer )
{
    char tmp_char[ 3 ] = { 0 };
    uint32_t tmp_fwf = 0;
    uint32_t tmp_fwef = 0;
    uint8_t tmp_resp[ 20 ] = { 0 };

    tts_parse_req( ISC_VERSION_REQ_MAIN, NULL, 0 );

    while( !tts_rsp_chk( ISC_VERSION_RESP_MAIN ) )
    {
        tts_get_resp();

        if( _parse_ind() )
            return _err_code;
    }

    tts_rsp_data( tmp_resp );
    sprintf(tmp_char, "%c", tmp_resp[ 0 ]);
    strcpy( buffer->hwver, tmp_char );
    strcat( buffer->hwver, "." );
    sprintf(tmp_char, "%c", tmp_resp[ 1 ]);
    strcat( buffer->hwver, tmp_char );
    sprintf(tmp_char, "%c", tmp_resp[ 2 ]);
    strcpy( buffer->fwver, tmp_char );
    strcat( buffer->fwver, "." );
    sprintf(tmp_char, "%c", tmp_resp[ 3 ]);
    strcat( buffer->fwver, tmp_char );
    strcat( buffer->fwver, "." );
    sprintf(tmp_char, "%c", tmp_resp[ 12 ]);
    strcat( buffer->fwver, tmp_char );

    tmp_fwf |= tmp_resp[ 4 ];
    tmp_fwf |= tmp_resp[ 5 ] << 8;
    tmp_fwf |= tmp_resp[ 6 ] << 16;
    tmp_fwf |= tmp_resp[ 7 ] << 24;
    buffer->fwf = (FF_t)tmp_fwf;
    tmp_fwef |= tmp_resp[ 8 ];
    tmp_fwef |= tmp_resp[ 9 ] << 8;
    tmp_fwef |= tmp_resp[ 10 ] << 16;
    tmp_fwef |= tmp_resp[ 11 ] << 24;
    buffer->fwef = (EFF_t)tmp_fwef;

    return 0x0000;
}

uint16_t tts_power_default_config()
{
    uint16_t tmp_resp = 0;
    uint8_t raw_resp[ 2 ] = { 0 };

    tts_parse_req( ISC_PMAN_CONFIG_REQ, ( uint8_t* )&_pman_conf, 4 );

    while( !tts_rsp_chk( ISC_PMAN_CONFIG_RESP ) )
    {
        tts_get_resp();

        if( _parse_ind() )
            return _err_code;
    }

    tts_rsp_data( raw_resp );

    tmp_resp |= raw_resp[ 0 ];
    tmp_resp |= raw_resp[ 1 ] << 8;

    return tmp_resp;
}

uint16_t tts_standby_enter()
{
    uint16_t tmp_resp = 0;
    uint8_t raw_resp[ 2 ] = { 0 };

    tts_parse_req( ISC_PMAN_STANDBY_ENTRY_REQ, NULL, 0 );

    while( !tts_rsp_chk( ISC_PMAN_STANDBY_ENTRY_RESP ) )
    {
        tts_get_resp();

        if( _parse_ind() )
            return _err_code;
    }

    tts_rsp_data( raw_resp );

    tmp_resp |= raw_resp[ 0 ];
    tmp_resp |= raw_resp[ 1 ] << 8;

    return tmp_resp;
}

uint16_t tts_standby_exit()
{
    wait( STBY_MODE_ENTERY );
    tts_parse_req( ISC_PMAN_STANDBY_EXIT_IND, NULL, 0 );

    while( !tts_rsp_chk( ISC_PMAN_STANDBY_EXIT_IND ) )
    {
        tts_get_resp();

        if( _parse_ind() )
            return _err_code;
    }

    return 0x0000;
}

uint16_t tts_audio_default_config()
{
    uint16_t tmp_resp = 0;
    uint8_t raw_resp[ 2 ] = { 0 };

    tts_parse_req( ISC_AUDIO_CONFIG_REQ, ( uint8_t* )&_audio_conf, 8 );

    while( !tts_rsp_chk( ISC_AUDIO_CONFIG_RESP ) )
    {
        tts_get_resp();

        if( _parse_ind() )
            return _err_code;
    }

    tts_rsp_data( raw_resp );

    tmp_resp |= raw_resp[ 0 ];
    tmp_resp |= raw_resp[ 1 ] << 8;

    return tmp_resp;
}

uint16_t tts_audio_config( int8_t audio_gain,
                           ASR_t sample_rate,
                           bool dac_control )
{
    ACONF_t audio_conf;
    uint16_t tmp_resp = 0;
    uint8_t raw_resp[ 2 ] = { 0 };

    if ( audio_gain < -48 || audio_gain > 18 )
        return 0xFFFF;

    if ( sample_rate != 0 || sample_rate != 1 || sample_rate != 3 )
        return 0xFFFF;

    audio_conf.ag = ( uint8_t )audio_gain;
    audio_conf.asr = sample_rate;
    audio_conf.dc = dac_control;

    tts_parse_req( ISC_AUDIO_CONFIG_REQ, ( uint8_t* )&audio_conf, 8 );

    while( !tts_rsp_chk( ISC_AUDIO_CONFIG_RESP ) )
    {
        tts_get_resp();

        if( _parse_ind() )
            return _err_code;
    }

    tts_rsp_data( raw_resp );

    tmp_resp |= raw_resp[ 0 ];
    tmp_resp |= raw_resp[ 1 ] << 8;

    return tmp_resp;
}

uint16_t tts_volume_set( int16_t gain )
{
    uint16_t tmp_resp = 0;
    uint8_t raw_resp[ 2 ] = { 0 };
    uint8_t tmp_gain[ 2 ] = { 0 };

    tmp_gain[ 0 ] = gain & 0x00FF;
    tmp_gain[ 1 ] = ( gain & 0xFF00 ) >> 8;

    tts_parse_req( ISC_AUDIO_VOULME_REQ, tmp_gain, 2 );

    while( !tts_rsp_chk( ISC_AUDIO_VOLUME_RESP ) )
    {
        tts_get_resp();

        if( _parse_ind() )
            return _err_code;
    }

    tts_rsp_data( raw_resp );

    tmp_resp |= raw_resp[ 0 ];
    tmp_resp |= raw_resp[ 1 ] << 8;

    return tmp_resp;
}

uint16_t tts_audio_mute()
{
    uint16_t tmp_resp = 0;
    uint8_t raw_resp[ 2 ] = { 0 };
    uint8_t tmp_mute[ 2 ] = { 1, 0 };

    tts_parse_req( ISC_AUDIO_MUTE_REQ, tmp_mute, 2 );

    while( !tts_rsp_chk( ISC_AUDIO_MUTE_RESP ) )
    {
        tts_get_resp();

        if( _parse_ind() )
            return _err_code;
    }

    tts_rsp_data( raw_resp );

    tmp_resp |= raw_resp[ 0 ];
    tmp_resp |= raw_resp[ 1 ] << 8;

    return tmp_resp;
}

uint16_t tts_audio_unmute()
{
    uint16_t tmp_resp = 0;
    uint8_t raw_resp[ 2 ] = { 0 };
    uint8_t tmp_mute[ 2 ] = { 0, 0 };

    tts_parse_req( ISC_AUDIO_MUTE_REQ, tmp_mute, 2 );

    while( !tts_rsp_chk( ISC_AUDIO_MUTE_RESP ) )
    {
        tts_get_resp();

        if( _parse_ind() )
            return _err_code;
    }

    tts_rsp_data( raw_resp );

    tmp_resp |= raw_resp[ 0 ];
    tmp_resp |= raw_resp[ 1 ] << 8;

    return tmp_resp;
}

uint16_t tts_default_config()
{
    uint16_t tmp_resp = 0;
    uint8_t raw_resp[ 2 ] = { 0 };

    tts_parse_req( ISC_TTS_CONFIG_REQ, ( uint8_t* )&_tts_conf, 8 );

    while( !tts_rsp_chk( ISC_TTS_CONFIG_RESP ) )
    {
        tts_get_resp();

        if( _parse_ind() )
            return _err_code;
    }

    tts_rsp_data( raw_resp );

    tmp_resp |= raw_resp[ 0 ];
    tmp_resp |= raw_resp[ 1 ] << 8;

    return tmp_resp;
}

uint16_t tts_config( uint8_t voice_type,
                     bool epson_parse,
                     TTSV_t language,
                     uint16_t speaking_rate )
{
    TTSCONF_t tts_conf;
    uint16_t tmp_resp = 0;
    uint8_t raw_resp[ 2 ] = { 0 };

    if ( voice_type > 8 )
        return 0xFFFF;

    if ( language > 4 )
        return 0xFFFF;

    if ( speaking_rate < 0x004B || speaking_rate > 0x0258 )
        return 0xFFFF;

    tts_conf.voice = voice_type;
    tts_conf.ep = epson_parse;
    tts_conf.lang = language;
    tts_conf.sr_wpm_lsb = ( speaking_rate & 0x00FF );
    tts_conf.sr_wpm_msb = ( speaking_rate & 0xFF00 ) >> 8;

    tts_parse_req( ISC_TTS_CONFIG_REQ, ( uint8_t* )&tts_conf, 8 );

    while( !tts_rsp_chk( ISC_TTS_CONFIG_RESP ) )
    {
        tts_get_resp();

        if( _parse_ind() )
            return _err_code;
    }

    tts_rsp_data( raw_resp );

    tmp_resp |= raw_resp[ 0 ];
    tmp_resp |= raw_resp[ 1 ] << 8;

    return tmp_resp;
}

uint16_t tts_speak( char *word )
{
    bool tmp_f              = false;
    char *wptr              = word;
    uint8_t raw_resp[ 2 ]   = { 0 };
    uint16_t tmp_resp       = 0;
    uint32_t wlen           = strlen( wptr );

    tts_parse_speak_req( ISC_TTS_SPEAK_REQ, _flush_enable, wptr, wlen );

    _tts_rdy_f = 0;
    _tts_fin_f = 0;

    while( !( tmp_f && _tts_rdy_f ) )
    {
        tts_get_resp();

        if( _parse_ind() )
            return _err_code;

        if( tts_rsp_chk( ISC_TTS_SPEAK_RESP ) )
        {
            tts_rsp_data( raw_resp );

            tmp_resp |= raw_resp[ 0 ];
            tmp_resp |= raw_resp[ 1 ] << 8;
            tmp_f = true;
        }
    }

    return tmp_resp;
}

uint16_t tts_pause( void )
{
    uint16_t tmp_resp = 0;
    uint8_t raw_resp[ 2 ] = { 0 };
    uint8_t tmp_pause[ 2 ] = { 1, 0 };

    tts_parse_req( ISC_TTS_PAUSE_REQ, tmp_pause, 2 );

    while( !tts_rsp_chk( ISC_TTS_PAUSE_RESP ) )
    {
        tts_get_resp();

        if( _parse_ind() )
            return _err_code;
    }

    tts_rsp_data( raw_resp );

    tmp_resp |= raw_resp[ 0 ];
    tmp_resp |= raw_resp[ 1 ] << 8;

    return tmp_resp;
}

uint16_t tts_unpause( void )
{
    uint16_t tmp_resp = 0;
    uint8_t raw_resp[ 2 ] = { 0 };
    uint8_t tmp_pause[ 2 ] = { 0 };

    tts_parse_req( ISC_TTS_PAUSE_REQ, tmp_pause, 2 );

    while( !tts_rsp_chk( ISC_TTS_PAUSE_RESP ) )
    {
        tts_get_resp();

        if( _parse_ind() )
            return _err_code;
    }

    tts_rsp_data( raw_resp );

    tmp_resp |= raw_resp[ 0 ];
    tmp_resp |= raw_resp[ 1 ] << 8;

    return tmp_resp;
}

uint16_t tts_stop( bool reset )
{
    uint16_t tmp_resp = 0;
    uint8_t raw_resp[ 2 ] = { 0 };
    uint8_t tmp_reset[ 2 ] = { 0 };

    if( reset )
        tmp_reset[ 0 ] = 0x01;

    tts_parse_req( ISC_TTS_STOP_REQ, tmp_reset, 2 );

    while( !tts_rsp_chk( ISC_TTS_STOP_RESP ) )
    {
        tts_get_resp();

        if( _parse_ind() )
            return _err_code;
    }

    tts_rsp_data( raw_resp );

    tmp_resp |= raw_resp[ 0 ];
    tmp_resp |= raw_resp[ 1 ] << 8;

    return tmp_resp;
}

uint16_t tts_user_dict( bool erase,
                        uint8_t *udict_data,
                        uint16_t count )
{
    uint16_t cnt = 2;
    uint16_t tmp_rsp = 0;
    uint8_t rsp_data[ 2 ] = { 0 };
    uint8_t tmp_data[ BOOT_MESSAGE_MAX ] = { 0 };

    if ( erase )
        tmp_data[ 0 ] = 1;

    while ( count-- )
        tmp_data[ cnt ++ ] = *( udict_data++ );

    tts_parse_req( ISC_TTS_UDICT_DATA_REQ, tmp_data, count + 2 );

    while( !tts_rsp_chk( ISC_TTS_UDICT_DATA_RESP ) )
    {
        tts_get_resp();

        if( _parse_ind() )
            return _err_code;
    }

    tts_rsp_data( rsp_data );

    tmp_rsp |= rsp_data[ 0 ];
    tmp_rsp |= rsp_data[ 1 ] << 8;

    return tmp_rsp;
}

uint16_t tts_codec_configure()
{
    uint16_t tmp_resp = 0;
    uint8_t raw_resp[ 2 ] = { 0 };
    uint8_t tmp_codec[ 32 ] = { 0 };

    tmp_codec[ 0 ] = 0x01;
    tmp_codec[ 1 ] = 0x01;
    tmp_codec[ 24 ] = 0x02;

    tts_parse_req( ISC_SPCODEC_CONFIG_REQ , tmp_codec, 32 );

    while( !tts_rsp_chk( ISC_SPCODEC_CONFIG_RESP ) )
    {
        tts_get_resp();

        if( _parse_ind() )
            return _err_code;
    }

    tts_rsp_data( raw_resp );

    tmp_resp |= raw_resp[ 0 ];
    tmp_resp |= raw_resp[ 1 ] << 8;

    return tmp_resp;
}

uint16_t tts_codec_start( uint8_t *codec_data,
                          uint16_t count )
{
    bool tmp_f = false;
    uint16_t tmp_resp = 0;
    uint8_t raw_resp[ 2 ] = { 0 };

    if ( count != 512 || count != 1024 || count != 2048 )
        return 0xFFFF;

    while( !_spc_fin_f )
    {
        tts_get_resp();

        if( _parse_ind() )
            return _err_code;
    }

    tts_parse_req( ISC_SPCODEC_START_REQ , codec_data, count );

    _spc_rdy_f = 0;
    _spc_fin_f = 0;

    while( !( tmp_f && _spc_rdy_f ) )
    {
        tts_get_resp();

        if( _parse_ind() )
            return _err_code;

        if( tts_rsp_chk( ISC_TTS_SPEAK_RESP ) )
        {
            tts_rsp_data( raw_resp );

            tmp_resp |= raw_resp[ 0 ];
            tmp_resp |= raw_resp[ 1 ] << 8;
            tmp_f = true;
        }
    }

    return tmp_resp;
}

uint16_t tts_codec_pause()
{
    uint16_t tmp_resp = 0;
    uint8_t raw_resp[ 2 ] = { 0 };
    uint8_t tmp_data[ 2 ] = { 1, 0 };

    tts_parse_req( ISC_SPCODEC_PAUSE_REQ , tmp_data, 2 );

    while( !tts_rsp_chk( ISC_SPCODEC_PAUSE_RESP ) )
    {
        tts_get_resp();

        if( _parse_ind() )
            return _err_code;
    }

    tts_rsp_data( raw_resp );

    tmp_resp |= raw_resp[ 0 ];
    tmp_resp |= raw_resp[ 1 ] << 8;

    return tmp_resp;
}

uint16_t tts_codec_unpause()
{
    uint16_t tmp_resp = 0;
    uint8_t raw_resp[ 2 ] = { 0 };
    uint8_t tmp_data[ 2 ] = { 0 };

    tts_parse_req( ISC_SPCODEC_PAUSE_REQ , tmp_data, 2 );

    while( !tts_rsp_chk( ISC_SPCODEC_PAUSE_RESP ) )
    {
        tts_get_resp();

        if( _parse_ind() )
            return _err_code;
    }

    tts_rsp_data( raw_resp );

    tmp_resp |= raw_resp[ 0 ];
    tmp_resp |= raw_resp[ 1 ] << 8;

    return tmp_resp;
}

uint16_t tts_codec_stop( bool reset )
{
    uint16_t tmp_resp = 0;
    uint8_t raw_resp[ 2 ] = { 0 };
    uint8_t tmp_data[ 2 ] = { 0 };

    if( reset )
        tmp_data[ 0 ] = 1;

    tts_parse_req( ISC_SPCODEC_STOP_REQ, tmp_data, 2 );

    while( !tts_rsp_chk( ISC_SPCODEC_PAUSE_RESP ) )
    {
        tts_get_resp();

        if( _parse_ind() )
            return _err_code;
    }

    tts_rsp_data( raw_resp );

    tmp_resp |= raw_resp[ 0 ];
    tmp_resp |= raw_resp[ 1 ] << 8;

    return tmp_resp;
}
/******************************************************************************
* text_to_speech_hw.c
*******************************************************************************/
void _read_rsp()
{
    uint8_t tmp_byte = 0;
    uint16_t tmp_len = 0;

    tts_hal_cs_low();
    
    tts_hal_read( &tmp_byte, 1 );

    if( tmp_byte == START_MESSAGE )
    {
       
        tts_hal_read( ( uint8_t* )&_last_rsp, 2 );
        tmp_len |= _last_rsp.len[ 0 ];
        tmp_len |= _last_rsp.len[ 1 ] << 8;
        tts_hal_read( ( uint8_t* )&_last_rsp + 2, tmp_len );
        
    } else {

        wait( 0.005 );
    }
   
    tts_hal_cs_high();
}

void _write_req(bool boot)
{
    uint16_t cnt = 0;
    uint8_t start = START_MESSAGE;

    cnt |= _last_req.len[ 0 ];
    cnt |= _last_req.len[ 1 ] << 8;
    
    tts_hal_cs_low();
    
    
    if(boot)
    {
        tts_hal_write( &start, 1, true );
        tts_hal_write( ( uint8_t* )&_last_req, cnt, true);
    }
    else
    {
        tts_hal_write( &start, 1, false );
        tts_hal_write( ( uint8_t* ) &_last_req, cnt, false );
    }    
   
    tts_hal_cs_high();
    
}

/******************************************************************************
* Public Function Definitions
*******************************************************************************/
void tts_hw_init( void )
{
    tts_hal_init();

    _ticker_f = false;
    _ticker = 0;

    _last_req.idx[ 0 ] = 0;
    _last_req.idx[ 1 ] = 0;
    _last_req.len[ 0 ] = 0;
    _last_req.len[ 1 ] = 0;
    memset( _last_req.payload, 0, MAIN_MESSAGE_MAX );

    _last_rsp.idx[ 0 ] = 255;
    _last_rsp.idx[ 1 ] = 255;
    _last_rsp.len[ 0 ] = 0;
    _last_rsp.len[ 1 ] = 0;
    memset( _last_rsp.payload, 0, RESP_MESSAGE_MAX );
}

void tts_tick_isr()
{
    _ticker++;

    if( _ticker > 500 )
        _ticker_f == true;
}

void tts_mute_cmd( bool cmd )
{
    if( cmd )
        tts_hal_mut_high();
    else
        tts_hal_mut_low();
}

void tts_parse_req( uint16_t req,
                    uint8_t *payload,
                    uint16_t pl_len )
{
    uint8_t *pl = payload;
    uint16_t i = 0;
    uint16_t tmp = pl_len + 4;
  
    
    
    _last_req.len[ 0 ] = tmp & 0x00FF;
    _last_req.len[ 1 ] = ( tmp & 0xFF00 ) >> 8;
    _last_req.idx[ 0 ] = req & 0x00FF;
    _last_req.idx[ 1 ] = ( req & 0xFF00 ) >> 8;
    _last_rsp.idx[ 0 ] = 0xFF;
    _last_rsp.idx[ 1 ] = 0xFF;
    
    if ( payload != NULL )
    {
        while ( pl_len-- )
            _last_req.payload[ i++ ] = *( pl++ );
           
    }
    
    _write_req(true);
}

void tts_parse_boot_img( const uint8_t *payload,
                         uint16_t pl_len )
{
    
   
    uint16_t i = 0;
    uint16_t tmp = pl_len + 0x04;
    
    _last_req.len[ 0 ] = tmp & 0x00FF;
    _last_req.len[ 1 ] = ( tmp & 0xFF00 ) >> 8;
    _last_req.idx[ 0 ] = 0x00;
    _last_req.idx[ 1 ] = 0x10;
    _last_rsp.idx[ 0 ] = 0xFF;
    _last_rsp.idx[ 1 ] = 0xFF;

    if ( payload != NULL )
    {
        while ( pl_len-- )
            _last_req.payload[ i++ ] = payload[ i ];  
    }

    _write_req(true);
}

void tts_parse_speak_req( uint16_t req,
                          uint8_t flush_en,
                          char *word,
                          uint16_t word_len )
{
    char *ptr = word;
    uint16_t i = 1;
    uint16_t tmp = word_len;

    word_len += 7;

    _last_req.len[ 0 ] = word_len & 0x00FF;
    _last_req.len[ 1 ] = ( word_len & 0xFF00 ) >> 8;
    _last_req.idx[ 0 ] = req & 0x00FF;
    _last_req.idx[ 1 ] = ( req & 0xFF00 ) >> 8;
    _last_rsp.idx[ 0 ] = 0xFF;
    _last_rsp.idx[ 1 ] = 0xFF;

    if( flush_en )
    {
        _last_req.payload[ 0 ] = 1;

    } else {

        _last_req.payload[ 0 ] = 0;
    }

    while( tmp-- )
        _last_req.payload[ i++ ] = *( ptr++ );

    _last_req.payload[ i++ ] = 0x20;
    _last_req.payload[ i ] = 0x00;

    _write_req(true);
}

void tts_get_resp()
{
    if( tts_hal_msg_rdy() )
    {
        _read_rsp();
    }
}

bool tts_rsp_chk( uint16_t idx )
{
    uint16_t tmp = 0;

    tmp |= _last_rsp.idx[ 0 ];
    tmp |= _last_rsp.idx[ 1 ] << 8;
    
   // pc.printf(" idx = %X\n\r", tmp);
    
   return ( idx == tmp ) ? true : false;
}

uint16_t tts_rsp_idx()
{
    uint16_t tmp = 0;

    tmp |= _last_rsp.idx[ 0 ];
    tmp |= _last_rsp.idx[ 1 ] << 8;

    return tmp;
}

void tts_rsp_data( uint8_t *buffer )
{
    uint8_t *bfr = buffer;
    uint16_t cnt = 0;
    uint8_t *ptr = _last_rsp.payload;

    cnt |= _last_rsp.len[ 0 ];
    cnt |= _last_rsp.len[ 1 ] << 8;
    cnt -= 4;

    while( cnt-- )
        *( bfr++ ) = *( ptr++ );
}

/*************** END OF FUNCTIONS *********************************************/