Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: Hexi_KW40Z Hexi_OLED_SSD1351 text_to_speak_mbed
Fork of iBreathe_Breathalyzer by
main.cpp
00001 /**************************************************************************** 00002 * Title : iBreathe Breathalyzer 00003 * Filename : Talking_breathalyzer 00004 * Author : Dave Clarke 00005 * Origin Date : 27/09/2016 00006 * Notes : Breathalyzer utilizing Hexiware, Alcohol click and 00007 Wolksense. Now with added voice thanks to the 00008 Text-To-Speech Click board 00009 *****************************************************************************/ 00010 /**************************CHANGE LIST ************************************** 00011 * 00012 * Date Software Version Initials Description 00013 * 07/10/16 1.0.0 DC Interface Created. 00014 * 00015 *****************************************************************************/ 00016 00017 /** 00018 * @page TEST_CFG Test Configurations 00019 * <h3> Test configuration : </h3> 00020 * @par 00021 * <ul> 00022 * <li><b> MCU </b> : MK64FN1M0XXX12 </li> 00023 * <li><b> Dev. Board </b> : HEXIWEAR </li> 00024 * <li><b> Oscillator </b> : 12 MHz external </li> 00025 * <li><b> Ext. Modules </b> : Alcohol Click on mikroBUS 1 </li> 00026 * <li><b> Ext. Modules </b> : TTS Click on mikroBUS 2 </li> 00027 * <li><b> SW </b> : mBed OS5 </li> 00028 * </ul> 00029 */ 00030 00031 /** 00032 * @mainpage 00033 * <h3> Breathalyser created with HEXIWEAR and mBed OS 5 </h3> 00034 * @par This will show you how much you've drunk and tell you with an Emoticon if 00035 * you're too hammered to even consider driving. Using the Hexiware app the readings 00036 * are transmitted to the cloud via bluetooth. Is it time to give up drinking yet?! 00037 * It now talks to you! 00038 00039 * <h3> Alcohol Features </h3> 00040 * @par Text to Speech Click, Alcohol click, Hexiwear docking station, Hexiware 00041 */ 00042 00043 /****************************************************************************** 00044 * Includes 00045 *******************************************************************************/ 00046 00047 #include "mbed.h" 00048 #include "Hexi_KW40Z.h" 00049 #include "Hexi_OLED_SSD1351.h" 00050 #include "OLED_types.h" 00051 #include "OpenSans_Font.h" 00052 #include "string.h" 00053 #include "iBreatheImages.h" 00054 #include "text_to_speech.h" 00055 #include "text_to_speech_hal.h" 00056 #include "text_to_speech_hw.h" 00057 #include "text_to_speech_img.h" 00058 00059 00060 /****************************************************************************** 00061 * Module Variable Definitions 00062 *******************************************************************************/ 00063 00064 #define LED_ON 0 00065 #define LED_OFF 1 00066 00067 // Pointers to: 00068 const uint8_t *welcome, // Welcome screen image 00069 *blank, // blank image 00070 *blow, // Start Blowing Image 00071 *drink, // You've been drinking image 00072 *drive, // Don't drive image 00073 *hang, // You'll have a hangover image 00074 *ini, // Initialising image 00075 *sober; // Sober as a judge image 00076 00077 const float Vadc_3V3 = 0.00005035; // 16-Bit ADC step 3V3/65535 = 0.05035 mV 00078 00079 float Vrl = 0, // Output voltage 00080 ambientAlc = 0, // Abmient Output voltage from sensor 00081 SensorRes = 0, // SensorRes (Ohm) - Sensor resistance 00082 SensorRes1 = 0, // SensorRes (Ohm) - Sensor resistance 00083 ppm = 0, // ppm 00084 ppm_1 = 0, // Ambient ppm variable 00085 ratio = 0; // SensorRes/LoadRes ratio 00086 00087 unsigned short adc_rd = 0; //Initialise anologue read variable 00088 00089 const uint8_t ppmText[] = "ppm:"; // text for PPM label 00090 00091 char text[20], // Text array variables 00092 text2[20], 00093 text3[20]; 00094 00095 float value[20], // initial sensor set up values 00096 value1[20]; // initial sensor set up values 00097 00098 bool isFirstBoot = true; 00099 00100 00101 /* Indication Flags */ 00102 static volatile bool _tts_rdy_f; 00103 static volatile bool _spc_rdy_f; 00104 static volatile bool _tts_fin_f; 00105 static volatile bool _spc_fin_f; 00106 00107 /* Error Buffers */ 00108 static uint16_t _req_err; 00109 static uint16_t _err_code; 00110 00111 /* Default Configuration */ 00112 static ACONF_t _audio_conf; 00113 static TTSCONF_t _tts_conf; 00114 static PMANCONF_t _pman_conf; 00115 00116 static bool _flush_enable; 00117 00118 /* Timer flag and counter */ 00119 static volatile bool _ticker_f; 00120 static volatile uint16_t _ticker; 00121 00122 /* Input and output buffers */ 00123 static ISC_REQ_t _last_req; 00124 static ISC_RESP_t _last_rsp; 00125 00126 static uint8_t test[ 8 ] = { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; 00127 int frequency = 750000; 00128 VER_t *version; 00129 /****************************************************************************** 00130 * Function Prototypes 00131 *******************************************************************************/ 00132 /* Checks for indications */ 00133 static int _parse_ind( void ); 00134 00135 /* Message block and error callback function pointers */ 00136 static void ( *_fatal_err_callback )( uint16_t *err_code ); 00137 static void ( *_err_callback )( uint16_t *err_code ); 00138 static void ( *_msg_block_callback )( uint16_t *msg_code, 00139 uint16_t *err_code ); 00140 00141 void voiceinit(void); 00142 void sysinit(void); 00143 void ReadSensor(); 00144 void CalculatePPM(int times, bool amb); 00145 void ambient(int times); 00146 void StartHaptic(void); 00147 void StopHaptic(void const *n); 00148 void ButtonUp(void); 00149 void txTask(void); 00150 void fatal_err( uint16_t *err ); 00151 void msg_blk( uint16_t *req, uint16_t *err ); 00152 00153 /****************************************************************************** 00154 * Instance setups 00155 *******************************************************************************/ 00156 00157 00158 /* Define timer for haptic feedback */ 00159 RtosTimer hapticTimer(StopHaptic, osTimerOnce); 00160 00161 //set up Analog read pin for alcohol sensor 00162 AnalogIn Alcohol(PTB2); 00163 00164 /* Instantiate the SSD1351 OLED Driver */ 00165 SSD1351 oled(PTB22,PTB21,PTC13,PTB20,PTE6, PTD15); /* (MOSI,SCLK,POWER,CS,RST,DC) */ 00166 00167 /* Get OLED Class Default Text Properties */ 00168 oled_text_properties_t textProperties = {0}; 00169 00170 /* Instantiate the Hexi KW40Z Driver (UART TX, UART RX) */ 00171 KW40Z kw40z_device(PTE24, PTE25); 00172 00173 /* LED and Haptic Set ups */ 00174 DigitalOut redLed(LED1); 00175 DigitalOut greenLed(LED2); 00176 DigitalOut blueLed(LED3); 00177 DigitalOut haptic(PTB9); 00178 00179 /* Instantiate the Click Text to Speech pinout */ 00180 DigitalOut TTS_RST(PTB19); 00181 DigitalOut TTS_CS(PTC3); 00182 DigitalOut TTS_MUTE(PTB3); 00183 DigitalIn TTS_RDY(PTB8); 00184 00185 //Instantiate SPI for comms with Speak module 00186 SPI TextToSpeech(PTC6, PTC7, PTC5); // MOSI, MISO, SCK 00187 00188 // Debug Serial 00189 Serial pc(USBTX, USBRX); 00190 00191 /****************************************************************************** 00192 * Bluetooth button functions and passkey function 00193 *******************************************************************************/ 00194 00195 void ButtonRight(void) 00196 { 00197 StartHaptic(); 00198 kw40z_device.ToggleAdvertisementMode(); 00199 blueLed = kw40z_device.GetAdvertisementMode(); /*Indicate BLE Advertisment Mode*/ 00200 redLed = !kw40z_device.GetAdvertisementMode(); /*Indicate BLE Advertisment Mode*/ 00201 greenLed = !kw40z_device.GetAdvertisementMode(); /*Indicate BLE Advertisment Mode*/ 00202 } 00203 00204 void ButtonLeft(void) 00205 { 00206 StartHaptic(); 00207 kw40z_device.ToggleAdvertisementMode(); 00208 blueLed = kw40z_device.GetAdvertisementMode(); /*Indicate BLE Advertisment Mode*/ 00209 redLed = !kw40z_device.GetAdvertisementMode(); /*Indicate BLE Advertisment Mode*/ 00210 greenLed = !kw40z_device.GetAdvertisementMode(); /*Indicate BLE Advertisment Mode*/ 00211 } 00212 00213 void PassKey(void) 00214 { 00215 StartHaptic(); 00216 strcpy((char *) text,"PAIR CODE"); 00217 oled.TextBox((uint8_t *)text,0,25,95,18); 00218 00219 /* Display Bond Pass Key in a 95px by 18px textbox at x=0,y=40 */ 00220 sprintf(text3,"%d", kw40z_device.GetPassKey()); 00221 oled.TextBox((uint8_t *)text3,0,40,95,18); 00222 } 00223 00224 /****************************************************************************** 00225 * Main 00226 *******************************************************************************/ 00227 ///////////////////////////////////////////////////////////////////////////////////////////////////////////// 00228 ///////////////////////////////////////////////////////////////////////////////////////////////////////////// 00229 ///////////////////////////////////////////////////////////////////////////////////////////////////////////// 00230 int main() 00231 { 00232 00233 00234 /* Set pointers to the BMPs stored in iBreatheImages.c */ 00235 welcome = iBreatheWS_bmp; // Welcome screen image 00236 blank = iBreatheBlank_bmp; // blank image 00237 blow = iBreatheBlow_bmp; // Start Blowing Image 00238 drink = iBreatheDrink_bmp; // You've been drinking image 00239 drive = iBreatheDrive_bmp; // Don't drive image 00240 hang = iBreatheHang_bmp; // You'll have a hangover image 00241 ini = iBreatheini_bmp; // Initialising image 00242 sober = iBreatheSober_bmp; // Sober as a judge image 00243 00244 /* Set initial Values */ 00245 sysinit(); 00246 00247 /* initialise voice engine */ 00248 voiceinit(); 00249 00250 /* Welcome message on reset */ 00251 tts_speak( "Hello, welcome to the eye brethalizer " ); 00252 wait(0.5); 00253 tts_speak( "please press start. " ); 00254 } 00255 00256 /****************************************************************************** 00257 * Public Function Definitions 00258 *******************************************************************************/ 00259 ///////////////////////////////////////////////////////////////////////////////////////////////////////////// 00260 ///////////////////////////////////////////////////////////////////////////////////////////////////////////// 00261 ///////////////////////////////////////////////////////////////////////////////////////////////////////////// 00262 /************************************************************************************************** 00263 * Function readSensor(void) 00264 * ------------------------------------------------------------------------------------------------- 00265 * Overview: Read sensor 00266 * Input: None 00267 * Output: None 00268 **************************************************************************************************/ 00269 00270 void ReadSensor() 00271 { 00272 /* Read 16 Bit Analog value */ 00273 adc_rd = Alcohol.read_u16(); 00274 00275 // pause 200ms 00276 Thread::wait(200); 00277 } 00278 00279 ///////////////////////////////////////////////////////////////////////////////////////////////////////////// 00280 ///////////////////////////////////////////////////////////////////////////////////////////////////////////// 00281 ///////////////////////////////////////////////////////////////////////////////////////////////////////////// 00282 /************************************************************************************************** 00283 * Function CalculatePPM(Int times, bool amb) 00284 * ------------------------------------------------------------------------------------------------- 00285 * Overview: Calculation of PPM 00286 * Input: times = Number of samples to take, amb sets either ambient reading or test reading (true for test) 00287 * Output: None 00288 **************************************************************************************************/ 00289 00290 void CalculatePPM(int times, bool amb) 00291 { 00292 float lgPPM; 00293 00294 /* Read values x times */ 00295 for(int x = 0; x < times; x++) 00296 { 00297 ReadSensor(); 00298 value[x] = ((float)adc_rd * Vadc_3V3); 00299 StartHaptic(); 00300 Thread::wait(50); 00301 } 00302 00303 /* Calculate the average value for accuratcy */ 00304 for(int y = 0; y < times; y++) 00305 { 00306 Vrl += value[y]; 00307 } 00308 Vrl = Vrl / times; 00309 00310 /* Set SensorRes reference value */ 00311 SensorRes = (Vrl / 3.3); 00312 00313 /* Set ratio */ 00314 ratio = SensorRes1 / SensorRes; 00315 00316 /* Convert to PPM */ 00317 lgPPM = ( log10( ratio ) * -1.5512 ) + 2.5911; 00318 00319 /* If true create test result, flase creates reference result */ 00320 if (amb == true) 00321 { 00322 ppm = pow( 10, lgPPM ); 00323 } 00324 else 00325 { 00326 ppm_1 = pow( 10, lgPPM ); 00327 } 00328 } 00329 00330 ///////////////////////////////////////////////////////////////////////////////////////////////////////////// 00331 ///////////////////////////////////////////////////////////////////////////////////////////////////////////// 00332 ///////////////////////////////////////////////////////////////////////////////////////////////////////////// 00333 /************************************************************************************************** 00334 * Function void ambient(int times) 00335 * ------------------------------------------------------------------------------------------------- 00336 * Overview: Reading of the Ambient Voltgage of the sensor for reference 00337 * Input: times = Number of samples to take 00338 * Output: None 00339 **************************************************************************************************/ 00340 00341 void ambient(int times) 00342 { 00343 /* Read ambient values x times flashing green led*/ 00344 for(int x = 0; x < times; x++) 00345 { 00346 redLed = LED_OFF; 00347 greenLed = LED_OFF; 00348 blueLed = LED_OFF; 00349 00350 ReadSensor(); 00351 value1[x] = (float)adc_rd * Vadc_3V3; 00352 00353 redLed = LED_OFF; 00354 greenLed = LED_ON; 00355 blueLed = LED_OFF; 00356 Thread::wait(48); 00357 } 00358 00359 /* Calculate the average value for accuratcy */ 00360 for(int y = 0; y < times; y++) 00361 { 00362 ambientAlc+=value1[y]; 00363 } 00364 ambientAlc = ambientAlc / times; 00365 00366 /* Set SensorRes1 reference value */ 00367 SensorRes1 = (ambientAlc / 3.3); 00368 } 00369 00370 ///////////////////////////////////////////////////////////////////////////////////////////////////////////// 00371 ///////////////////////////////////////////////////////////////////////////////////////////////////////////// 00372 ///////////////////////////////////////////////////////////////////////////////////////////////////////////// 00373 /************************************************************************************************** 00374 * Function void StartHaptic(void) 00375 * ------------------------------------------------------------------------------------------------- 00376 * Overview: Start Buzzing haptic motor 00377 * Input: None 00378 * Output: None 00379 **************************************************************************************************/ 00380 00381 void StartHaptic(void) 00382 { 00383 hapticTimer.start(50); 00384 haptic = 1; 00385 } 00386 00387 ///////////////////////////////////////////////////////////////////////////////////////////////////////////// 00388 ///////////////////////////////////////////////////////////////////////////////////////////////////////////// 00389 ///////////////////////////////////////////////////////////////////////////////////////////////////////////// 00390 /************************************************************************************************** 00391 * Function void StopHaptic(void) 00392 * ------------------------------------------------------------------------------------------------- 00393 * Overview: Stop Buzzing haptic motor 00394 * Input: None 00395 * Output: None 00396 **************************************************************************************************/ 00397 00398 void StopHaptic(void const *n) { 00399 haptic = 0; 00400 hapticTimer.stop(); 00401 } 00402 00403 ///////////////////////////////////////////////////////////////////////////////////////////////////////////// 00404 ///////////////////////////////////////////////////////////////////////////////////////////////////////////// 00405 ///////////////////////////////////////////////////////////////////////////////////////////////////////////// 00406 /************************************************************************************************** 00407 * Function void ButtonUp(void) 00408 * ------------------------------------------------------------------------------------------------- 00409 * Overview: Function called whe up button pressed, Begins Breathilyzer testing procedure 00410 * Input: None 00411 * Output: None 00412 **************************************************************************************************/ 00413 00414 void ButtonUp(void) 00415 { 00416 StartHaptic(); 00417 00418 bool Ref = false; 00419 bool Test = true; 00420 00421 /* LED set to green for test beginning*/ 00422 redLed = LED_OFF; 00423 greenLed = LED_ON; 00424 blueLed = LED_OFF; 00425 00426 /* Fill 96px by 96px Screen with 96px by 96px Initialising Image starting at x=0,y=0 */ 00427 oled.DrawImage(ini,0,0); 00428 00429 /* first boot bug work around to stop junk values */ 00430 if (isFirstBoot == true) 00431 { 00432 /*read ambient atmosphere levels with 10 samples and set flag to show it's ambient basline figure*/ 00433 ambient(1); 00434 CalculatePPM(1,Ref); 00435 isFirstBoot = false; 00436 } 00437 00438 00439 /*read ambient atmosphere levels with 10 samples and set flag to show it's ambient basline figure*/ 00440 tts_speak( "initializing" ); 00441 ambient(10); 00442 CalculatePPM(10,Ref); 00443 00444 00445 /* Fill 96px by 96px Screen with 96px by 96px Blowing Image starting at x=0,y=0 */ 00446 oled.DrawImage(blow,0,0); 00447 tts_speak( "please blow until buzzing stops" ); 00448 /*read breathe alcohol levels with 10 samples and set flag to show it's breathilyzer test figure*/ 00449 CalculatePPM(10,Test); 00450 00451 /*Calculate the difference in Alcohol level based on Ambient and test sample*/ 00452 ppm = ppm - ppm_1; 00453 00454 /*Throw away any values less than 0*/ 00455 if (ppm < 0) 00456 { 00457 ppm = 0; 00458 } 00459 00460 /* Fill 96px by 96px Screen with 96px by 96px Blank Background Image starting at x=0,y=0 */ 00461 oled.DrawImage(blank,0,0); 00462 tts_speak( "Test Complete" ); 00463 Thread::wait(500); 00464 /* Show Calculated alcohol level in PPM and send data via bluetooth to the cloud */ 00465 oled.SetTextProperties(&textProperties); 00466 oled.Label(ppmText,20,36); 00467 tts_speak( "you blew" ); 00468 sprintf(text,"%.2f",ppm); 00469 Thread::wait(50); 00470 tts_speak( text ); 00471 oled.Label((uint8_t *)text,50,36); 00472 Thread::wait(50); 00473 tts_speak( "pee pee emm" ); 00474 Thread::wait(1000); 00475 00476 /* Currently sending to the Pressure variable as a temp place holder */ 00477 kw40z_device.SendiBreathe(ppm); // this is used for custom Hexiware app 00478 kw40z_device.SendPressure(ppm * 10); // using this to record on Wolksense Cloud 00479 00480 00481 /* You've got a Hangover coming!*/ 00482 if ( ppm > 200) 00483 { 00484 tts_speak("you have got a hang over coming"); 00485 redLed = LED_ON; 00486 greenLed = LED_OFF; 00487 blueLed = LED_OFF; 00488 00489 StartHaptic(); 00490 00491 /* Fill 96px by 96px Screen with 96px by 96px Hangover Image starting at x=0,y=0 */ 00492 oled.DrawImage(hang,0,0); 00493 } 00494 00495 /* You Shouldn't drive */ 00496 else if (ppm < 200 && ppm > 150) 00497 { 00498 tts_speak("you shouldn't drive"); 00499 redLed = LED_ON; 00500 greenLed = LED_OFF; 00501 blueLed = LED_ON; 00502 00503 StartHaptic(); 00504 00505 /* Fill 96px by 96px Screen with 96px by 96px Don't Drive Image starting at x=0,y=0 */ 00506 oled.DrawImage(drive,0,0); 00507 } 00508 00509 /* You've had a drink */ 00510 else if (ppm < 150 && ppm > 50) 00511 { 00512 tts_speak("you have had a drinky"); 00513 redLed = LED_OFF; 00514 greenLed = LED_ON; 00515 blueLed = LED_ON; 00516 00517 StartHaptic(); 00518 00519 /* Fill 96px by 96px Screen with 96px by 96px Had a drink Image starting at x=0,y=0 */ 00520 oled.DrawImage(drink,0,0); 00521 } 00522 00523 /* Sober as a judge*/ 00524 else 00525 { 00526 tts_speak("you are as sober as a judge"); 00527 redLed = LED_OFF; 00528 greenLed = LED_ON; 00529 blueLed = LED_OFF; 00530 00531 StartHaptic(); 00532 oled.DrawImage(sober,0,0); 00533 } 00534 Thread::wait(5000); 00535 00536 /* Go back to start screen */ 00537 sysinit(); 00538 } 00539 00540 ///////////////////////////////////////////////////////////////////////////////////////////////////////////// 00541 ///////////////////////////////////////////////////////////////////////////////////////////////////////////// 00542 ///////////////////////////////////////////////////////////////////////////////////////////////////////////// 00543 /************************************************************************************************** 00544 * Function void sysint(void) 00545 * ------------------------------------------------------------------------------------------------- 00546 * Overview: System Initial Values Set up 00547 * Input: None 00548 * Output: None 00549 **************************************************************************************************/ 00550 void sysinit(void) 00551 { 00552 /* Set LED to Blue by default*/ 00553 redLed = LED_OFF; 00554 greenLed = LED_OFF; 00555 blueLed = LED_ON; 00556 00557 /* Turn on the backlight of the OLED Display */ 00558 oled.DimScreenON(); 00559 00560 /* Fill 96px by 96px Screen with 96px by 96px Welcome Image starting at x=0,y=0 */ 00561 oled.DrawImage(welcome,0,0); 00562 00563 /* Register callbacks to application functions */ 00564 kw40z_device.attach_buttonUp(&ButtonUp); 00565 kw40z_device.attach_buttonLeft(&ButtonLeft); 00566 kw40z_device.attach_buttonRight(&ButtonRight); 00567 kw40z_device.attach_passkey(&PassKey); 00568 00569 /* Send sensor data to bluetooth */ 00570 kw40z_device.SendSetApplicationMode(GUI_CURRENT_APP_SENSOR_TAG); 00571 00572 /* Change font color to White */ 00573 oled.GetTextProperties(&textProperties); 00574 textProperties.fontColor = COLOR_WHITE; 00575 oled.SetTextProperties(&textProperties); 00576 } 00577 00578 ///////////////////////////////////////////////////////////////////////////////////////////////////////////// 00579 ///////////////////////////////////////////////////////////////////////////////////////////////////////////// 00580 ///////////////////////////////////////////////////////////////////////////////////////////////////////////// 00581 /************************************************************************************************** 00582 * Function void voiceinit(void) 00583 * ------------------------------------------------------------------------------------------------- 00584 * Overview: initialise voice engine 00585 * Input: None 00586 * Output: None 00587 **************************************************************************************************/ 00588 void voiceinit(void) 00589 { 00590 00591 /*setting up the SPI defaults*/ 00592 TextToSpeech.lock(); 00593 TextToSpeech.format(8,3); 00594 TextToSpeech.frequency(frequency); 00595 TextToSpeech.unlock(); 00596 00597 /* initialise voice */ 00598 pc.printf("System Init Done!\r\n"); 00599 tts_init(); 00600 pc.printf("tts Init Done!\r\n"); 00601 tts_setup(); 00602 pc.printf("tts setup Done!\r\n"); 00603 tts_msg_block_callback( msg_blk ); 00604 tts_fatal_err_callback( fatal_err ); 00605 tts_config( 0x10, false, TTSV_US, 0x0080 ); 00606 tts_unmute(); 00607 00608 } 00609 00610 ///////////////////////////////////////////////////////////////////////////////////////////////////////////// 00611 ///////////////////////////////////////////////////////////////////////////////////////////////////////////// 00612 ///////////////////////////////////////////////////////////////////////////////////////////////////////////// 00613 /************************************************************************************************** 00614 * Function msg_blk( uint16_t *req, uint16_t *err ) 00615 * ------------------------------------------------------------------------------------------------- 00616 * Overview: receive a blocked message from S1V30120; 00617 **************************************************************************************************/ 00618 void msg_blk( uint16_t *req, uint16_t *err ) 00619 { 00620 char txt[ 6 ]; 00621 00622 pc.printf( " MSG BLOCKED \r\n" ); 00623 sprintf( txt, "%x\r\n", *req ); 00624 pc.printf( txt ); 00625 sprintf( txt, "%x\r\n", *err ); 00626 pc.printf( txt ); 00627 } 00628 ///////////////////////////////////////////////////////////////////////////////////////////////////////////// 00629 ///////////////////////////////////////////////////////////////////////////////////////////////////////////// 00630 ///////////////////////////////////////////////////////////////////////////////////////////////////////////// 00631 /************************************************************************************************** 00632 * Function fatal_err( uint16_t *err ) 00633 * ------------------------------------------------------------------------------------------------- 00634 * Overview: error detected 00635 **************************************************************************************************/ 00636 void fatal_err( uint16_t *err ) 00637 { 00638 pc.printf( "Fatal Error Detected" ); 00639 tts_init(); 00640 tts_fatal_err_callback( fatal_err ); 00641 } 00642 00643 ///////////////////////////////////////////////////////////////////////////////////////////////////////////// 00644 ///////////////////////////////////////////////////////////////////////////////////////////////////////////// 00645 ///////////////////////////////////////////////////////////////////////////////////////////////////////////// 00646 /************************************************************************************************** 00647 * text_to_speech_hal.c 00648 * ------------------------------------------------------------------------------------------------- 00649 * Overview: Functions to control SPI interface. 00650 **************************************************************************************************/ 00651 00652 void tts_hal_cs_high() 00653 { 00654 00655 TTS_CS = 1; 00656 } 00657 00658 void tts_hal_cs_low() 00659 { 00660 TTS_CS = 0; 00661 00662 } 00663 00664 void tts_hal_mut_high() 00665 { 00666 TTS_MUTE = 1; 00667 } 00668 00669 void tts_hal_mut_low() 00670 { 00671 TTS_MUTE = 0; 00672 } 00673 00674 void tts_hal_reset( void ) 00675 { 00676 tts_hal_cs_high(); 00677 TTS_RST = 0; 00678 tts_hal_write_pad(1); 00679 wait(0.01); 00680 TTS_RST = 1; 00681 wait(POR_TIME); 00682 } 00683 00684 bool tts_hal_msg_rdy( void ) 00685 { 00686 return TTS_RDY; 00687 } 00688 00689 void tts_hal_init() 00690 { 00691 tts_hal_reset(); 00692 tts_hal_cs_high(); 00693 tts_hal_mut_low(); 00694 } 00695 00696 void tts_hal_write( uint8_t *buffer, 00697 uint16_t count, bool boot ) 00698 { 00699 TextToSpeech.lock(); 00700 while( count-- ) 00701 { 00702 if(!boot) 00703 pc.printf("%02X\r\n", *buffer); 00704 00705 TextToSpeech.write( *buffer++ ); 00706 00707 } 00708 TextToSpeech.unlock(); 00709 } 00710 00711 00712 void tts_hal_write_pad( int cnt ) 00713 { 00714 TextToSpeech.lock(); 00715 tts_hal_cs_low(); 00716 while(cnt--) 00717 { 00718 TextToSpeech.write( PADDING_BYTE ); 00719 } 00720 00721 tts_hal_cs_high(); 00722 TextToSpeech.unlock(); 00723 } 00724 00725 void tts_hal_read( uint8_t *buffer, 00726 uint16_t count ) 00727 { 00728 TextToSpeech.lock(); 00729 while(count--) 00730 { 00731 *buffer++ = TextToSpeech.write( DUMMY_BYTE ); //read spi bus 00732 00733 00734 //pc.printf("buffer = %X\n\r", *buffer); 00735 } 00736 TextToSpeech.unlock(); 00737 } 00738 00739 ///////////////////////////////////////////////////////////////////////////////////////////////////////////// 00740 ///////////////////////////////////////////////////////////////////////////////////////////////////////////// 00741 ///////////////////////////////////////////////////////////////////////////////////////////////////////////// 00742 /************************************************************************************************** 00743 * text_to_speech.c 00744 * ------------------------------------------------------------------------------------------------- 00745 * Overview: Functions to control the setup and speech controls 00746 **************************************************************************************************/ 00747 00748 static int _parse_ind( void ) 00749 { 00750 uint16_t rsp_idx = tts_rsp_idx(); 00751 if ( rsp_idx == ISC_MSG_BLOCKED_RESP ) 00752 { 00753 uint8_t rsp_data[ 4 ] = { 0 }; 00754 00755 _req_err = 0; 00756 _err_code = 0; 00757 00758 tts_rsp_data( rsp_data ); 00759 00760 _req_err |= rsp_data[ 0 ]; 00761 _req_err |= rsp_data[ 1 ] << 8; 00762 _err_code |= rsp_data[ 2 ]; 00763 _err_code |= rsp_data[ 3 ] << 8; 00764 00765 if( _msg_block_callback != NULL ) 00766 _msg_block_callback( &_req_err, &_err_code ); 00767 00768 return 1; 00769 00770 } else if ( rsp_idx == ISC_ERROR_IND ) { 00771 00772 uint8_t rsp_data[ 4 ] = { 0 }; 00773 00774 _req_err = 0; 00775 _err_code = 0; 00776 00777 tts_rsp_data( rsp_data ); 00778 00779 _err_code |= rsp_data[ 0 ]; 00780 _err_code |= rsp_data[ 1 ] << 8; 00781 00782 if ( _err_code && _err_code < 0x8000 ) 00783 { 00784 if( _err_callback != NULL ) 00785 _err_callback( &_err_code ); 00786 00787 } else if ( _err_code && _err_code > 0x7FFF ) { 00788 00789 if( _fatal_err_callback != NULL ) 00790 _fatal_err_callback( &_err_code ); 00791 } 00792 00793 return 1; 00794 00795 } else if ( rsp_idx == ISC_TTS_READY_IND ) { 00796 00797 _tts_rdy_f = 1; 00798 00799 } else if ( rsp_idx == ISC_SPCODEC_READY_IND ) { 00800 00801 _spc_rdy_f = 1; 00802 00803 } else if ( rsp_idx == ISC_TTS_FINISHED_IND ) { 00804 00805 _tts_fin_f = 1; 00806 00807 } else if ( rsp_idx == ISC_SPCODEC_FINISHED_IND ) { 00808 00809 _spc_fin_f = 1; 00810 } 00811 00812 return 0; 00813 } 00814 00815 void tts_init() 00816 { 00817 _req_err = 0; 00818 _err_code = 0; 00819 00820 _tts_rdy_f = true; 00821 _spc_rdy_f = true; 00822 _tts_fin_f = true; 00823 _spc_fin_f = true; 00824 00825 _audio_conf.as = 0x00; 00826 _audio_conf.ag = 0x43; 00827 _audio_conf.amp = 0x00; 00828 _audio_conf.asr = ASR_11KHZ; 00829 _audio_conf.ar = 0x00; 00830 _audio_conf.atc = 0x00; 00831 _audio_conf.acs = 0x00; 00832 _audio_conf.dc = 0x00; 00833 00834 _tts_conf.sr = 0x01; 00835 _tts_conf.voice = 0x00; 00836 _tts_conf.ep = 0x00; 00837 _tts_conf.lang = TTSV_US; 00838 _tts_conf.sr_wpm_lsb = 0xc8; 00839 _tts_conf.sr_wpm_msb = 0x00; 00840 _tts_conf.ds = 0x00; 00841 _tts_conf.res = 0x00; 00842 00843 _pman_conf.am_lsb = 0x01; 00844 _pman_conf.am_msb = 0x00; 00845 _pman_conf.spi_clk = 0x01; 00846 _pman_conf.pad = PADDING_BYTE; 00847 00848 _flush_enable = false; 00849 00850 _msg_block_callback = NULL; 00851 _fatal_err_callback = NULL; 00852 _err_callback = NULL; 00853 00854 tts_hw_init(); 00855 } 00856 00857 void tts_msg_block_callback( void( *msg_blk_ptr )( uint16_t *req_ptr, 00858 uint16_t *err_ptr ) ) 00859 { 00860 _msg_block_callback = msg_blk_ptr; 00861 } 00862 00863 void tts_fatal_err_callback( void( *fatal_err_ptr )( uint16_t *err_ptr ) ) 00864 { 00865 _fatal_err_callback = fatal_err_ptr; 00866 } 00867 00868 void tts_err_callback( void( *error_ptr )( uint16_t *err_ptr ) ) 00869 { 00870 _err_callback = error_ptr; 00871 } 00872 00873 void tts_mute() 00874 { 00875 tts_mute_cmd( true ); 00876 } 00877 00878 void tts_unmute() 00879 { 00880 tts_mute_cmd( false ); 00881 } 00882 00883 00884 void tts_setup() 00885 { 00886 //check HW version 00887 tts_version_boot(); 00888 00889 int succ = tts_image_load( (uint8_t*)TTS_INIT_DATA, sizeof( TTS_INIT_DATA ) ); 00890 00891 if ( succ != 0x0001 ) 00892 { 00893 // image load failed, try turning it off and on again 00894 pc.printf("tts init data failed!\n\r"); 00895 pc.printf("returned value: %X\n\r", succ); 00896 while(1); 00897 } 00898 pc.printf("tts image load done\n\r"); 00899 succ = tts_image_exec(); 00900 00901 if ( succ != 0x0001 ) 00902 { 00903 // image boot failed, try turning it off and on again 00904 pc.printf("tts image exec failed!\n\r"); 00905 pc.printf("returned value: %X\n\r", succ); 00906 while(1); 00907 } 00908 pc.printf("tts image exec done\n\r"); 00909 00910 tts_interface_test(); 00911 pc.printf("tts interface test done\n\r"); 00912 00913 tts_power_default_config(); 00914 pc.printf("tts power default done\n\r"); 00915 00916 tts_audio_default_config(); 00917 pc.printf("tts audio default done\n\r"); 00918 00919 tts_volume_set( 0 ); 00920 pc.printf("tts volume set done\n\r"); 00921 00922 tts_default_config(); 00923 pc.printf("tts default config done\n\r"); 00924 } 00925 00926 void tts_version_boot( void ) 00927 { 00928 00929 uint8_t tmp_resp[ 16 ] = { 0 }; 00930 00931 wait( RESET_TO_BOOT_TIME ); 00932 00933 tts_parse_req( ISC_VERSION_REQ_BOOT, NULL, 0 ); 00934 00935 while( !tts_rsp_chk( ISC_VERSION_RESP_BOOT ) ) 00936 { 00937 tts_get_resp(); 00938 } 00939 tts_hal_write_pad( 16); 00940 tts_rsp_data( tmp_resp ); 00941 pc.printf("hwver0 %X \n\r", tmp_resp[ 0 ]); 00942 pc.printf("hwver1 %X \n\r", tmp_resp[ 1 ]); 00943 } 00944 00945 uint16_t tts_image_load(const uint8_t *image, 00946 uint16_t count ) 00947 { 00948 uint16_t tmp_resp = 0; 00949 uint16_t index = 0; 00950 uint8_t raw_resp[ 2 ] = { 0 }; 00951 00952 while ( ( count - index ) > ( BOOT_MESSAGE_MAX - 4 ) ) 00953 { 00954 00955 tts_parse_boot_img( image + index, BOOT_MESSAGE_MAX - 4 ); 00956 wait(0.01); 00957 index += ( BOOT_MESSAGE_MAX - 4 ); 00958 } 00959 tts_parse_boot_img( image + index, count - index ); 00960 wait(0.01); 00961 00962 while( !tts_rsp_chk( ISC_BOOT_LOAD_RESP ) ) 00963 { 00964 tts_get_resp(); 00965 00966 if( _parse_ind() ) 00967 return _err_code; 00968 } 00969 tts_rsp_data( raw_resp ); 00970 00971 tmp_resp |= raw_resp[ 0 ]; 00972 tmp_resp |= raw_resp[ 1 ] << 8; 00973 00974 return tmp_resp; 00975 } 00976 00977 uint16_t tts_image_exec() 00978 { 00979 uint16_t tmp_resp = 0; 00980 uint8_t raw_resp[ 2 ] = { 0 }; 00981 00982 tts_parse_req( ISC_BOOT_RUN_REQ, NULL, 0 ); 00983 00984 while( !tts_rsp_chk( ISC_BOOT_RUN_RESP ) ) 00985 { 00986 tts_get_resp(); 00987 00988 if( _parse_ind() ) 00989 return _err_code; 00990 } 00991 tts_rsp_data( raw_resp ); 00992 00993 tmp_resp |= raw_resp[ 0 ]; 00994 tmp_resp |= raw_resp[ 1 ] << 8; 00995 00996 return tmp_resp; 00997 } 00998 00999 uint16_t tts_interface_test() 01000 { 01001 uint16_t tmp_resp = 0; 01002 uint8_t raw_resp[ 2 ] = { 0 }; 01003 01004 wait( BOOT_TO_MAIN_MODE ); 01005 01006 tts_parse_req( ISC_TEST_REQ, test, 8 ); 01007 01008 while( !tts_rsp_chk( ISC_TEST_RESP ) ) 01009 { 01010 tts_get_resp(); 01011 01012 if( _parse_ind() ) 01013 return _err_code; 01014 } 01015 01016 tts_rsp_data( raw_resp ); 01017 01018 tmp_resp |= raw_resp[ 0 ]; 01019 tmp_resp |= raw_resp[ 1 ] << 8; 01020 01021 return tmp_resp; 01022 } 01023 01024 uint16_t tts_version_main( VER_t *buffer ) 01025 { 01026 char tmp_char[ 3 ] = { 0 }; 01027 uint32_t tmp_fwf = 0; 01028 uint32_t tmp_fwef = 0; 01029 uint8_t tmp_resp[ 20 ] = { 0 }; 01030 01031 tts_parse_req( ISC_VERSION_REQ_MAIN, NULL, 0 ); 01032 01033 while( !tts_rsp_chk( ISC_VERSION_RESP_MAIN ) ) 01034 { 01035 tts_get_resp(); 01036 01037 if( _parse_ind() ) 01038 return _err_code; 01039 } 01040 01041 tts_rsp_data( tmp_resp ); 01042 sprintf(tmp_char, "%c", tmp_resp[ 0 ]); 01043 strcpy( buffer->hwver, tmp_char ); 01044 strcat( buffer->hwver, "." ); 01045 sprintf(tmp_char, "%c", tmp_resp[ 1 ]); 01046 strcat( buffer->hwver, tmp_char ); 01047 sprintf(tmp_char, "%c", tmp_resp[ 2 ]); 01048 strcpy( buffer->fwver, tmp_char ); 01049 strcat( buffer->fwver, "." ); 01050 sprintf(tmp_char, "%c", tmp_resp[ 3 ]); 01051 strcat( buffer->fwver, tmp_char ); 01052 strcat( buffer->fwver, "." ); 01053 sprintf(tmp_char, "%c", tmp_resp[ 12 ]); 01054 strcat( buffer->fwver, tmp_char ); 01055 01056 tmp_fwf |= tmp_resp[ 4 ]; 01057 tmp_fwf |= tmp_resp[ 5 ] << 8; 01058 tmp_fwf |= tmp_resp[ 6 ] << 16; 01059 tmp_fwf |= tmp_resp[ 7 ] << 24; 01060 buffer->fwf = (FF_t)tmp_fwf; 01061 tmp_fwef |= tmp_resp[ 8 ]; 01062 tmp_fwef |= tmp_resp[ 9 ] << 8; 01063 tmp_fwef |= tmp_resp[ 10 ] << 16; 01064 tmp_fwef |= tmp_resp[ 11 ] << 24; 01065 buffer->fwef = (EFF_t)tmp_fwef; 01066 01067 return 0x0000; 01068 } 01069 01070 uint16_t tts_power_default_config() 01071 { 01072 uint16_t tmp_resp = 0; 01073 uint8_t raw_resp[ 2 ] = { 0 }; 01074 01075 tts_parse_req( ISC_PMAN_CONFIG_REQ, ( uint8_t* )&_pman_conf, 4 ); 01076 01077 while( !tts_rsp_chk( ISC_PMAN_CONFIG_RESP ) ) 01078 { 01079 tts_get_resp(); 01080 01081 if( _parse_ind() ) 01082 return _err_code; 01083 } 01084 01085 tts_rsp_data( raw_resp ); 01086 01087 tmp_resp |= raw_resp[ 0 ]; 01088 tmp_resp |= raw_resp[ 1 ] << 8; 01089 01090 return tmp_resp; 01091 } 01092 01093 uint16_t tts_standby_enter() 01094 { 01095 uint16_t tmp_resp = 0; 01096 uint8_t raw_resp[ 2 ] = { 0 }; 01097 01098 tts_parse_req( ISC_PMAN_STANDBY_ENTRY_REQ, NULL, 0 ); 01099 01100 while( !tts_rsp_chk( ISC_PMAN_STANDBY_ENTRY_RESP ) ) 01101 { 01102 tts_get_resp(); 01103 01104 if( _parse_ind() ) 01105 return _err_code; 01106 } 01107 01108 tts_rsp_data( raw_resp ); 01109 01110 tmp_resp |= raw_resp[ 0 ]; 01111 tmp_resp |= raw_resp[ 1 ] << 8; 01112 01113 return tmp_resp; 01114 } 01115 01116 uint16_t tts_standby_exit() 01117 { 01118 wait( STBY_MODE_ENTERY ); 01119 tts_parse_req( ISC_PMAN_STANDBY_EXIT_IND, NULL, 0 ); 01120 01121 while( !tts_rsp_chk( ISC_PMAN_STANDBY_EXIT_IND ) ) 01122 { 01123 tts_get_resp(); 01124 01125 if( _parse_ind() ) 01126 return _err_code; 01127 } 01128 01129 return 0x0000; 01130 } 01131 01132 uint16_t tts_audio_default_config() 01133 { 01134 uint16_t tmp_resp = 0; 01135 uint8_t raw_resp[ 2 ] = { 0 }; 01136 01137 tts_parse_req( ISC_AUDIO_CONFIG_REQ, ( uint8_t* )&_audio_conf, 8 ); 01138 01139 while( !tts_rsp_chk( ISC_AUDIO_CONFIG_RESP ) ) 01140 { 01141 tts_get_resp(); 01142 01143 if( _parse_ind() ) 01144 return _err_code; 01145 } 01146 01147 tts_rsp_data( raw_resp ); 01148 01149 tmp_resp |= raw_resp[ 0 ]; 01150 tmp_resp |= raw_resp[ 1 ] << 8; 01151 01152 return tmp_resp; 01153 } 01154 01155 uint16_t tts_audio_config( int8_t audio_gain, 01156 ASR_t sample_rate, 01157 bool dac_control ) 01158 { 01159 ACONF_t audio_conf; 01160 uint16_t tmp_resp = 0; 01161 uint8_t raw_resp[ 2 ] = { 0 }; 01162 01163 if ( audio_gain < -48 || audio_gain > 18 ) 01164 return 0xFFFF; 01165 01166 if ( sample_rate != 0 || sample_rate != 1 || sample_rate != 3 ) 01167 return 0xFFFF; 01168 01169 audio_conf.ag = ( uint8_t )audio_gain; 01170 audio_conf.asr = sample_rate; 01171 audio_conf.dc = dac_control; 01172 01173 tts_parse_req( ISC_AUDIO_CONFIG_REQ, ( uint8_t* )&audio_conf, 8 ); 01174 01175 while( !tts_rsp_chk( ISC_AUDIO_CONFIG_RESP ) ) 01176 { 01177 tts_get_resp(); 01178 01179 if( _parse_ind() ) 01180 return _err_code; 01181 } 01182 01183 tts_rsp_data( raw_resp ); 01184 01185 tmp_resp |= raw_resp[ 0 ]; 01186 tmp_resp |= raw_resp[ 1 ] << 8; 01187 01188 return tmp_resp; 01189 } 01190 01191 uint16_t tts_volume_set( int16_t gain ) 01192 { 01193 uint16_t tmp_resp = 0; 01194 uint8_t raw_resp[ 2 ] = { 0 }; 01195 uint8_t tmp_gain[ 2 ] = { 0 }; 01196 01197 tmp_gain[ 0 ] = gain & 0x00FF; 01198 tmp_gain[ 1 ] = ( gain & 0xFF00 ) >> 8; 01199 01200 tts_parse_req( ISC_AUDIO_VOULME_REQ, tmp_gain, 2 ); 01201 01202 while( !tts_rsp_chk( ISC_AUDIO_VOLUME_RESP ) ) 01203 { 01204 tts_get_resp(); 01205 01206 if( _parse_ind() ) 01207 return _err_code; 01208 } 01209 01210 tts_rsp_data( raw_resp ); 01211 01212 tmp_resp |= raw_resp[ 0 ]; 01213 tmp_resp |= raw_resp[ 1 ] << 8; 01214 01215 return tmp_resp; 01216 } 01217 01218 uint16_t tts_audio_mute() 01219 { 01220 uint16_t tmp_resp = 0; 01221 uint8_t raw_resp[ 2 ] = { 0 }; 01222 uint8_t tmp_mute[ 2 ] = { 1, 0 }; 01223 01224 tts_parse_req( ISC_AUDIO_MUTE_REQ, tmp_mute, 2 ); 01225 01226 while( !tts_rsp_chk( ISC_AUDIO_MUTE_RESP ) ) 01227 { 01228 tts_get_resp(); 01229 01230 if( _parse_ind() ) 01231 return _err_code; 01232 } 01233 01234 tts_rsp_data( raw_resp ); 01235 01236 tmp_resp |= raw_resp[ 0 ]; 01237 tmp_resp |= raw_resp[ 1 ] << 8; 01238 01239 return tmp_resp; 01240 } 01241 01242 uint16_t tts_audio_unmute() 01243 { 01244 uint16_t tmp_resp = 0; 01245 uint8_t raw_resp[ 2 ] = { 0 }; 01246 uint8_t tmp_mute[ 2 ] = { 0, 0 }; 01247 01248 tts_parse_req( ISC_AUDIO_MUTE_REQ, tmp_mute, 2 ); 01249 01250 while( !tts_rsp_chk( ISC_AUDIO_MUTE_RESP ) ) 01251 { 01252 tts_get_resp(); 01253 01254 if( _parse_ind() ) 01255 return _err_code; 01256 } 01257 01258 tts_rsp_data( raw_resp ); 01259 01260 tmp_resp |= raw_resp[ 0 ]; 01261 tmp_resp |= raw_resp[ 1 ] << 8; 01262 01263 return tmp_resp; 01264 } 01265 01266 uint16_t tts_default_config() 01267 { 01268 uint16_t tmp_resp = 0; 01269 uint8_t raw_resp[ 2 ] = { 0 }; 01270 01271 tts_parse_req( ISC_TTS_CONFIG_REQ, ( uint8_t* )&_tts_conf, 8 ); 01272 01273 while( !tts_rsp_chk( ISC_TTS_CONFIG_RESP ) ) 01274 { 01275 tts_get_resp(); 01276 01277 if( _parse_ind() ) 01278 return _err_code; 01279 } 01280 01281 tts_rsp_data( raw_resp ); 01282 01283 tmp_resp |= raw_resp[ 0 ]; 01284 tmp_resp |= raw_resp[ 1 ] << 8; 01285 01286 return tmp_resp; 01287 } 01288 01289 uint16_t tts_config( uint8_t voice_type, 01290 bool epson_parse, 01291 TTSV_t language, 01292 uint16_t speaking_rate ) 01293 { 01294 TTSCONF_t tts_conf; 01295 uint16_t tmp_resp = 0; 01296 uint8_t raw_resp[ 2 ] = { 0 }; 01297 01298 if ( voice_type > 8 ) 01299 return 0xFFFF; 01300 01301 if ( language > 4 ) 01302 return 0xFFFF; 01303 01304 if ( speaking_rate < 0x004B || speaking_rate > 0x0258 ) 01305 return 0xFFFF; 01306 01307 tts_conf.voice = voice_type; 01308 tts_conf.ep = epson_parse; 01309 tts_conf.lang = language; 01310 tts_conf.sr_wpm_lsb = ( speaking_rate & 0x00FF ); 01311 tts_conf.sr_wpm_msb = ( speaking_rate & 0xFF00 ) >> 8; 01312 01313 tts_parse_req( ISC_TTS_CONFIG_REQ, ( uint8_t* )&tts_conf, 8 ); 01314 01315 while( !tts_rsp_chk( ISC_TTS_CONFIG_RESP ) ) 01316 { 01317 tts_get_resp(); 01318 01319 if( _parse_ind() ) 01320 return _err_code; 01321 } 01322 01323 tts_rsp_data( raw_resp ); 01324 01325 tmp_resp |= raw_resp[ 0 ]; 01326 tmp_resp |= raw_resp[ 1 ] << 8; 01327 01328 return tmp_resp; 01329 } 01330 01331 uint16_t tts_speak( char *word ) 01332 { 01333 bool tmp_f = false; 01334 char *wptr = word; 01335 uint8_t raw_resp[ 2 ] = { 0 }; 01336 uint16_t tmp_resp = 0; 01337 uint32_t wlen = strlen( wptr ); 01338 01339 tts_parse_speak_req( ISC_TTS_SPEAK_REQ, _flush_enable, wptr, wlen ); 01340 01341 _tts_rdy_f = 0; 01342 _tts_fin_f = 0; 01343 01344 while( !( tmp_f && _tts_rdy_f ) ) 01345 { 01346 tts_get_resp(); 01347 01348 if( _parse_ind() ) 01349 return _err_code; 01350 01351 if( tts_rsp_chk( ISC_TTS_SPEAK_RESP ) ) 01352 { 01353 tts_rsp_data( raw_resp ); 01354 01355 tmp_resp |= raw_resp[ 0 ]; 01356 tmp_resp |= raw_resp[ 1 ] << 8; 01357 tmp_f = true; 01358 } 01359 } 01360 01361 return tmp_resp; 01362 } 01363 01364 uint16_t tts_pause( void ) 01365 { 01366 uint16_t tmp_resp = 0; 01367 uint8_t raw_resp[ 2 ] = { 0 }; 01368 uint8_t tmp_pause[ 2 ] = { 1, 0 }; 01369 01370 tts_parse_req( ISC_TTS_PAUSE_REQ, tmp_pause, 2 ); 01371 01372 while( !tts_rsp_chk( ISC_TTS_PAUSE_RESP ) ) 01373 { 01374 tts_get_resp(); 01375 01376 if( _parse_ind() ) 01377 return _err_code; 01378 } 01379 01380 tts_rsp_data( raw_resp ); 01381 01382 tmp_resp |= raw_resp[ 0 ]; 01383 tmp_resp |= raw_resp[ 1 ] << 8; 01384 01385 return tmp_resp; 01386 } 01387 01388 uint16_t tts_unpause( void ) 01389 { 01390 uint16_t tmp_resp = 0; 01391 uint8_t raw_resp[ 2 ] = { 0 }; 01392 uint8_t tmp_pause[ 2 ] = { 0 }; 01393 01394 tts_parse_req( ISC_TTS_PAUSE_REQ, tmp_pause, 2 ); 01395 01396 while( !tts_rsp_chk( ISC_TTS_PAUSE_RESP ) ) 01397 { 01398 tts_get_resp(); 01399 01400 if( _parse_ind() ) 01401 return _err_code; 01402 } 01403 01404 tts_rsp_data( raw_resp ); 01405 01406 tmp_resp |= raw_resp[ 0 ]; 01407 tmp_resp |= raw_resp[ 1 ] << 8; 01408 01409 return tmp_resp; 01410 } 01411 01412 uint16_t tts_stop( bool reset ) 01413 { 01414 uint16_t tmp_resp = 0; 01415 uint8_t raw_resp[ 2 ] = { 0 }; 01416 uint8_t tmp_reset[ 2 ] = { 0 }; 01417 01418 if( reset ) 01419 tmp_reset[ 0 ] = 0x01; 01420 01421 tts_parse_req( ISC_TTS_STOP_REQ, tmp_reset, 2 ); 01422 01423 while( !tts_rsp_chk( ISC_TTS_STOP_RESP ) ) 01424 { 01425 tts_get_resp(); 01426 01427 if( _parse_ind() ) 01428 return _err_code; 01429 } 01430 01431 tts_rsp_data( raw_resp ); 01432 01433 tmp_resp |= raw_resp[ 0 ]; 01434 tmp_resp |= raw_resp[ 1 ] << 8; 01435 01436 return tmp_resp; 01437 } 01438 01439 uint16_t tts_user_dict( bool erase, 01440 uint8_t *udict_data, 01441 uint16_t count ) 01442 { 01443 uint16_t cnt = 2; 01444 uint16_t tmp_rsp = 0; 01445 uint8_t rsp_data[ 2 ] = { 0 }; 01446 uint8_t tmp_data[ BOOT_MESSAGE_MAX ] = { 0 }; 01447 01448 if ( erase ) 01449 tmp_data[ 0 ] = 1; 01450 01451 while ( count-- ) 01452 tmp_data[ cnt ++ ] = *( udict_data++ ); 01453 01454 tts_parse_req( ISC_TTS_UDICT_DATA_REQ, tmp_data, count + 2 ); 01455 01456 while( !tts_rsp_chk( ISC_TTS_UDICT_DATA_RESP ) ) 01457 { 01458 tts_get_resp(); 01459 01460 if( _parse_ind() ) 01461 return _err_code; 01462 } 01463 01464 tts_rsp_data( rsp_data ); 01465 01466 tmp_rsp |= rsp_data[ 0 ]; 01467 tmp_rsp |= rsp_data[ 1 ] << 8; 01468 01469 return tmp_rsp; 01470 } 01471 01472 uint16_t tts_codec_configure() 01473 { 01474 uint16_t tmp_resp = 0; 01475 uint8_t raw_resp[ 2 ] = { 0 }; 01476 uint8_t tmp_codec[ 32 ] = { 0 }; 01477 01478 tmp_codec[ 0 ] = 0x01; 01479 tmp_codec[ 1 ] = 0x01; 01480 tmp_codec[ 24 ] = 0x02; 01481 01482 tts_parse_req( ISC_SPCODEC_CONFIG_REQ , tmp_codec, 32 ); 01483 01484 while( !tts_rsp_chk( ISC_SPCODEC_CONFIG_RESP ) ) 01485 { 01486 tts_get_resp(); 01487 01488 if( _parse_ind() ) 01489 return _err_code; 01490 } 01491 01492 tts_rsp_data( raw_resp ); 01493 01494 tmp_resp |= raw_resp[ 0 ]; 01495 tmp_resp |= raw_resp[ 1 ] << 8; 01496 01497 return tmp_resp; 01498 } 01499 01500 uint16_t tts_codec_start( uint8_t *codec_data, 01501 uint16_t count ) 01502 { 01503 bool tmp_f = false; 01504 uint16_t tmp_resp = 0; 01505 uint8_t raw_resp[ 2 ] = { 0 }; 01506 01507 if ( count != 512 || count != 1024 || count != 2048 ) 01508 return 0xFFFF; 01509 01510 while( !_spc_fin_f ) 01511 { 01512 tts_get_resp(); 01513 01514 if( _parse_ind() ) 01515 return _err_code; 01516 } 01517 01518 tts_parse_req( ISC_SPCODEC_START_REQ , codec_data, count ); 01519 01520 _spc_rdy_f = 0; 01521 _spc_fin_f = 0; 01522 01523 while( !( tmp_f && _spc_rdy_f ) ) 01524 { 01525 tts_get_resp(); 01526 01527 if( _parse_ind() ) 01528 return _err_code; 01529 01530 if( tts_rsp_chk( ISC_TTS_SPEAK_RESP ) ) 01531 { 01532 tts_rsp_data( raw_resp ); 01533 01534 tmp_resp |= raw_resp[ 0 ]; 01535 tmp_resp |= raw_resp[ 1 ] << 8; 01536 tmp_f = true; 01537 } 01538 } 01539 01540 return tmp_resp; 01541 } 01542 01543 uint16_t tts_codec_pause() 01544 { 01545 uint16_t tmp_resp = 0; 01546 uint8_t raw_resp[ 2 ] = { 0 }; 01547 uint8_t tmp_data[ 2 ] = { 1, 0 }; 01548 01549 tts_parse_req( ISC_SPCODEC_PAUSE_REQ , tmp_data, 2 ); 01550 01551 while( !tts_rsp_chk( ISC_SPCODEC_PAUSE_RESP ) ) 01552 { 01553 tts_get_resp(); 01554 01555 if( _parse_ind() ) 01556 return _err_code; 01557 } 01558 01559 tts_rsp_data( raw_resp ); 01560 01561 tmp_resp |= raw_resp[ 0 ]; 01562 tmp_resp |= raw_resp[ 1 ] << 8; 01563 01564 return tmp_resp; 01565 } 01566 01567 uint16_t tts_codec_unpause() 01568 { 01569 uint16_t tmp_resp = 0; 01570 uint8_t raw_resp[ 2 ] = { 0 }; 01571 uint8_t tmp_data[ 2 ] = { 0 }; 01572 01573 tts_parse_req( ISC_SPCODEC_PAUSE_REQ , tmp_data, 2 ); 01574 01575 while( !tts_rsp_chk( ISC_SPCODEC_PAUSE_RESP ) ) 01576 { 01577 tts_get_resp(); 01578 01579 if( _parse_ind() ) 01580 return _err_code; 01581 } 01582 01583 tts_rsp_data( raw_resp ); 01584 01585 tmp_resp |= raw_resp[ 0 ]; 01586 tmp_resp |= raw_resp[ 1 ] << 8; 01587 01588 return tmp_resp; 01589 } 01590 01591 uint16_t tts_codec_stop( bool reset ) 01592 { 01593 uint16_t tmp_resp = 0; 01594 uint8_t raw_resp[ 2 ] = { 0 }; 01595 uint8_t tmp_data[ 2 ] = { 0 }; 01596 01597 if( reset ) 01598 tmp_data[ 0 ] = 1; 01599 01600 tts_parse_req( ISC_SPCODEC_STOP_REQ, tmp_data, 2 ); 01601 01602 while( !tts_rsp_chk( ISC_SPCODEC_PAUSE_RESP ) ) 01603 { 01604 tts_get_resp(); 01605 01606 if( _parse_ind() ) 01607 return _err_code; 01608 } 01609 01610 tts_rsp_data( raw_resp ); 01611 01612 tmp_resp |= raw_resp[ 0 ]; 01613 tmp_resp |= raw_resp[ 1 ] << 8; 01614 01615 return tmp_resp; 01616 } 01617 ///////////////////////////////////////////////////////////////////////////////////////////////////////////// 01618 ///////////////////////////////////////////////////////////////////////////////////////////////////////////// 01619 ///////////////////////////////////////////////////////////////////////////////////////////////////////////// 01620 /************************************************************************************************** 01621 * text_to_speech_hw.c 01622 * ------------------------------------------------------------------------------------------------- 01623 * Overview: Mainly read and write functions with parsing 01624 **************************************************************************************************/ 01625 01626 void _read_rsp() 01627 { 01628 uint8_t tmp_byte = 0; 01629 uint16_t tmp_len = 0; 01630 01631 tts_hal_cs_low(); 01632 01633 tts_hal_read( &tmp_byte, 1 ); 01634 01635 if( tmp_byte == START_MESSAGE ) 01636 { 01637 tts_hal_read( ( uint8_t* )&_last_rsp, 2 ); 01638 tmp_len |= _last_rsp.len[ 0 ]; 01639 tmp_len |= _last_rsp.len[ 1 ] << 8; 01640 tts_hal_read( ( uint8_t* )&_last_rsp + 2, tmp_len ); 01641 01642 } else { 01643 01644 wait( 0.005 ); 01645 } 01646 01647 tts_hal_cs_high(); 01648 } 01649 01650 void _write_req(bool boot) 01651 { 01652 uint16_t cnt = 0; 01653 uint8_t start = START_MESSAGE; 01654 01655 cnt |= _last_req.len[ 0 ]; 01656 cnt |= _last_req.len[ 1 ] << 8; 01657 01658 tts_hal_cs_low(); 01659 01660 01661 if(boot) // use for debug - displays the current buffer on serial 01662 { 01663 tts_hal_write( &start, 1, true ); 01664 tts_hal_write( ( uint8_t* )&_last_req, cnt, true); 01665 } 01666 else 01667 { 01668 tts_hal_write( &start, 1, false ); 01669 tts_hal_write( ( uint8_t* ) &_last_req, cnt, false ); 01670 } 01671 01672 tts_hal_cs_high(); 01673 01674 } 01675 01676 /****************************************************************************** 01677 * Public Function Definitions 01678 *******************************************************************************/ 01679 void tts_hw_init( void ) 01680 { 01681 tts_hal_init(); 01682 01683 _ticker_f = false; 01684 _ticker = 0; 01685 01686 _last_req.idx[ 0 ] = 0; 01687 _last_req.idx[ 1 ] = 0; 01688 _last_req.len[ 0 ] = 0; 01689 _last_req.len[ 1 ] = 0; 01690 memset( _last_req.payload, 0, MAIN_MESSAGE_MAX ); 01691 01692 _last_rsp.idx[ 0 ] = 255; 01693 _last_rsp.idx[ 1 ] = 255; 01694 _last_rsp.len[ 0 ] = 0; 01695 _last_rsp.len[ 1 ] = 0; 01696 memset( _last_rsp.payload, 0, RESP_MESSAGE_MAX ); 01697 } 01698 01699 void tts_tick_isr() 01700 { 01701 _ticker++; 01702 01703 if( _ticker > 500 ) 01704 _ticker_f == true; 01705 } 01706 01707 void tts_mute_cmd( bool cmd ) 01708 { 01709 if( cmd ) 01710 tts_hal_mut_high(); 01711 else 01712 tts_hal_mut_low(); 01713 } 01714 01715 void tts_parse_req( uint16_t req, 01716 uint8_t *payload, 01717 uint16_t pl_len ) 01718 { 01719 uint8_t *pl = payload; 01720 uint16_t i = 0; 01721 uint16_t tmp = pl_len + 4; 01722 01723 _last_req.len[ 0 ] = tmp & 0x00FF; 01724 _last_req.len[ 1 ] = ( tmp & 0xFF00 ) >> 8; 01725 _last_req.idx[ 0 ] = req & 0x00FF; 01726 _last_req.idx[ 1 ] = ( req & 0xFF00 ) >> 8; 01727 _last_rsp.idx[ 0 ] = 0xFF; 01728 _last_rsp.idx[ 1 ] = 0xFF; 01729 01730 if ( payload != NULL ) 01731 { 01732 while ( pl_len-- ) 01733 _last_req.payload[ i++ ] = *( pl++ ); 01734 01735 } 01736 01737 _write_req(true); 01738 } 01739 01740 void tts_parse_boot_img( const uint8_t *payload, 01741 uint16_t pl_len ) 01742 { 01743 uint16_t i = 0; 01744 uint16_t tmp = pl_len + 0x04; 01745 01746 _last_req.len[ 0 ] = tmp & 0x00FF; 01747 _last_req.len[ 1 ] = ( tmp & 0xFF00 ) >> 8; 01748 _last_req.idx[ 0 ] = 0x00; 01749 _last_req.idx[ 1 ] = 0x10; 01750 _last_rsp.idx[ 0 ] = 0xFF; 01751 _last_rsp.idx[ 1 ] = 0xFF; 01752 01753 if ( payload != NULL ) 01754 { 01755 while ( pl_len-- ) 01756 _last_req.payload[ i++ ] = payload[ i ]; 01757 } 01758 01759 _write_req(true); 01760 } 01761 01762 void tts_parse_speak_req( uint16_t req, 01763 uint8_t flush_en, 01764 char *word, 01765 uint16_t word_len ) 01766 { 01767 char *ptr = word; 01768 uint16_t i = 1; 01769 uint16_t tmp = word_len; 01770 01771 word_len += 7; 01772 01773 _last_req.len[ 0 ] = word_len & 0x00FF; 01774 _last_req.len[ 1 ] = ( word_len & 0xFF00 ) >> 8; 01775 _last_req.idx[ 0 ] = req & 0x00FF; 01776 _last_req.idx[ 1 ] = ( req & 0xFF00 ) >> 8; 01777 _last_rsp.idx[ 0 ] = 0xFF; 01778 _last_rsp.idx[ 1 ] = 0xFF; 01779 01780 if( flush_en ) 01781 { 01782 _last_req.payload[ 0 ] = 1; 01783 01784 } else { 01785 01786 _last_req.payload[ 0 ] = 0; 01787 } 01788 01789 while( tmp-- ) 01790 _last_req.payload[ i++ ] = *( ptr++ ); 01791 01792 _last_req.payload[ i++ ] = 0x20; 01793 _last_req.payload[ i ] = 0x00; 01794 01795 _write_req(true); 01796 } 01797 01798 void tts_get_resp() 01799 { 01800 // only read if ready 01801 if( tts_hal_msg_rdy() ) 01802 { 01803 _read_rsp(); 01804 } 01805 } 01806 01807 bool tts_rsp_chk( uint16_t idx ) 01808 { 01809 uint16_t tmp = 0; 01810 01811 tmp |= _last_rsp.idx[ 0 ]; 01812 tmp |= _last_rsp.idx[ 1 ] << 8; 01813 01814 return ( idx == tmp ) ? true : false; 01815 } 01816 01817 uint16_t tts_rsp_idx() 01818 { 01819 uint16_t tmp = 0; 01820 01821 tmp |= _last_rsp.idx[ 0 ]; 01822 tmp |= _last_rsp.idx[ 1 ] << 8; 01823 01824 return tmp; 01825 } 01826 01827 void tts_rsp_data( uint8_t *buffer ) 01828 { 01829 uint8_t *bfr = buffer; 01830 uint16_t cnt = 0; 01831 uint8_t *ptr = _last_rsp.payload; 01832 01833 cnt |= _last_rsp.len[ 0 ]; 01834 cnt |= _last_rsp.len[ 1 ] << 8; 01835 cnt -= 4; 01836 01837 while( cnt-- ) 01838 *( bfr++ ) = *( ptr++ ); 01839 } 01840 01841 /*************** END OF FUNCTIONS *********************************************/
Generated on Mon Jul 18 2022 00:12:08 by
1.7.2
