Stand Alone mBed OS Text To Speech Click Board Example
Fork of Hexi_Click_Relay-v3_Example by
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 *********************************************/