The "GR-PEACH_Audio_Playback_7InchLCD_Sample" is a sample code that can provides high-resolution audio playback of FLAC format files. It also allows the user to audio-playback control functions such as play, pause, and stop by manipulating key switches.
Dependencies: GR-PEACH_video R_BSP TLV320_RBSP USBHost_custom
Fork of GR-PEACH_Audio_Playback_Sample by
audio_out.cpp
00001 /******************************************************************************* 00002 * DISCLAIMER 00003 * This software is supplied by Renesas Electronics Corporation and is only 00004 * intended for use with Renesas products. No other uses are authorized. This 00005 * software is owned by Renesas Electronics Corporation and is protected under 00006 * all applicable laws, including copyright laws. 00007 * THIS SOFTWARE IS PROVIDED "AS IS" AND RENESAS MAKES NO WARRANTIES REGARDING 00008 * THIS SOFTWARE, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING BUT NOT 00009 * LIMITED TO WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE 00010 * AND NON-INFRINGEMENT. ALL SUCH WARRANTIES ARE EXPRESSLY DISCLAIMED. 00011 * TO THE MAXIMUM EXTENT PERMITTED NOT PROHIBITED BY LAW, NEITHER RENESAS 00012 * ELECTRONICS CORPORATION NOR ANY OF ITS AFFILIATED COMPANIES SHALL BE LIABLE 00013 * FOR ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES FOR 00014 * ANY REASON RELATED TO THIS SOFTWARE, EVEN IF RENESAS OR ITS AFFILIATES HAVE 00015 * BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 00016 * Renesas reserves the right, without notice, to make changes to this software 00017 * and to discontinue the availability of this software. By using this software, 00018 * you agree to the additional terms and conditions found by accessing the 00019 * following link: 00020 * http://www.renesas.com/disclaimer* 00021 * Copyright (C) 2015 Renesas Electronics Corporation. All rights reserved. 00022 *******************************************************************************/ 00023 00024 #include "mbed.h" 00025 #include "rtos.h" 00026 #include "misratypes.h" 00027 #include "r_errno.h" 00028 #include "decode.h" 00029 #include "audio_out.h" 00030 #include "display.h" 00031 #include "TLV320_RBSP.h" 00032 00033 /*--- Macro definition of mbed-rtos mail ---*/ 00034 #define MAIL_QUEUE_SIZE (12) /* Queue size */ 00035 #define MAIL_PARAM_NUM (3) /* Elements number of mail parameter array */ 00036 00037 /* aud_mail_t */ 00038 #define MAIL_PARAM0 (0) /* Index number of mail parameter array */ 00039 #define MAIL_PARAM1 (1) /* Index number of mail parameter array */ 00040 #define MAIL_PARAM2 (2) /* Index number of mail parameter array */ 00041 00042 #define MAIL_PARAM_NON (0u) /* Value of unused element of mail parameter array */ 00043 00044 /* mail_id = AUD_MAILID_DATA_OUT */ 00045 #define MAIL_DATA_OUT_CB (MAIL_PARAM0) /* Callback function */ 00046 00047 /* mail_id = AUD_MAILID_ZERO_OUT : No parameter */ 00048 00049 /* mail_id = AUD_MAILID_SCUX_READ_FIN */ 00050 #define MAIL_SCUX_READ_RESULT (MAIL_PARAM0) /* Result of the process */ 00051 #define MAIL_SCUX_READ_BUF_INDEX (MAIL_PARAM1) /* Index number of PCM buffer */ 00052 #define MAIL_SCUX_READ_BYTE_NUM (MAIL_PARAM2) /* Byte number of PCM data */ 00053 00054 /* mail_id = AUD_MAILID_PCM_OUT_FIN */ 00055 #define MAIL_PCM_OUT_RESULT (MAIL_PARAM0) /* Result of the process */ 00056 #define MAIL_PCM_OUT_BUF_INDEX (MAIL_PARAM1) /* Index number of PCM buffer */ 00057 00058 /* mail_id = AUD_MAILID_GET_AUDIO */ 00059 #define MAIL_GET_AUDIO_CB (MAIL_PARAM0) /* Callback function */ 00060 #define MAIL_GET_AUDIO_BUF (MAIL_PARAM1) /* Pointer to the display buffer array */ 00061 #define MAIL_GET_AUDIO_NUM (MAIL_PARAM2) /* Elements number of the display buffer array */ 00062 00063 /*--- Macro definition of PCM buffer ---*/ 00064 #define UNIT_TIME_MS (10u) /* Unit time of PCM data processing (ms) */ 00065 #define SEC_TO_MSEC (1000u) 00066 00067 /* Sample number per unit time (ms) */ 00068 #define SAMPLE_PER_UNIT_MS ((UNIT_TIME_MS * DEC_OUTPUT_SAMPLE_RATE) / SEC_TO_MSEC) 00069 00070 #define OUTPUT_START_TRIGGER (3) /* Numerical value of the trigger */ 00071 /* to start the output of PCM data */ 00072 #define OUTPUT_UPDATE_TRIGGER (1) /* Numerical value of the trigger */ 00073 /* to update the output of PCM data */ 00074 00075 #define PCM_BUF_NUM (DEC_SCUX_READ_NUM) 00076 #define TOTAL_SAMPLE_NUM (SAMPLE_PER_UNIT_MS * DEC_OUTPUT_CHANNEL_NUM) 00077 00078 /*--- Macro definition of TLV320_RBSP ---*/ 00079 #define AUDIO_POWER_MIC_OFF (0x02) /* Microphone input :OFF */ 00080 #define AUDIO_INT_LEVEL (0x80) 00081 #define AUDIO_READ_NUM (0) 00082 #define AUDIO_WRITE_NUM (PCM_BUF_NUM) 00083 #define ERR_MSG_TLV320_RBSP_WRITE "\nError: TLV320_RBSP::write()\n" 00084 00085 /* 4 bytes aligned. No cache memory. */ 00086 #define NC_BSS_SECT __attribute__((section("NC_BSS"),aligned(4))) 00087 #define ERR_MSG_RECV_ILLEGAL_MAIL "\nError: aud_thread function received illegal mail.\n" 00088 00089 /*--- User defined types of mbed-rtos mail ---*/ 00090 typedef enum { 00091 AUD_MAILID_DUMMY = 0, 00092 AUD_MAILID_DATA_OUT, /* Requests the output of PCM data. */ 00093 AUD_MAILID_ZERO_OUT, /* Requests the output of zero data. */ 00094 AUD_MAILID_SCUX_READ_FIN, /* Finished the reading process of SCUX. */ 00095 AUD_MAILID_PCM_OUT_FIN, /* Finished the output of data. */ 00096 AUD_MAILID_GET_AUDIO, /* Requests the audio data acquisition. */ 00097 AUD_MAILID_NUM 00098 } AUD_MAIL_ID; 00099 00100 typedef struct { 00101 AUD_MAIL_ID mail_id; 00102 uint32_t param[MAIL_PARAM_NUM]; 00103 } aud_mail_t; 00104 00105 /*--- User defined types of audio output thread ---*/ 00106 /* The control data of PCM buffer. */ 00107 typedef struct { 00108 uint32_t pcm_buf_index; /* Index of PCM buffer array */ 00109 uint32_t pcm_buf_remain_cnt; /* Counter of the remain elements in PCM buffer array */ 00110 uint32_t pcm_stock_cnt; /* Counter of the stock elements in PCM buffer array */ 00111 uint32_t output_trg_cnt; /* Number of the trigger to start the output of PCM data */ 00112 } pcm_buf_ctrl_t; 00113 00114 static Mail<aud_mail_t, MAIL_QUEUE_SIZE> mail_box; 00115 00116 static void init_pcm_buf(pcm_buf_ctrl_t * const p_ctrl); 00117 static bool read_scux(int32_t (* const p_buf)[TOTAL_SAMPLE_NUM], const uint32_t buf_id); 00118 static bool write_audio(TLV320_RBSP * const p_audio, int32_t (* const p_buf)[TOTAL_SAMPLE_NUM], const uint32_t buf_id); 00119 static void read_callback(void * p_data, int32_t result, void * p_app_data); 00120 static void pcm_out_callback(void * p_data, int32_t result, void * p_app_data); 00121 static bool send_mail(const AUD_MAIL_ID mail_id, const uint32_t param0, 00122 const uint32_t param1, const uint32_t param2); 00123 static bool recv_mail(AUD_MAIL_ID * const p_mail_id, uint32_t * const p_param0, 00124 uint32_t * const p_param1, uint32_t * const p_param2); 00125 00126 void aud_thread(void const *argument) 00127 { 00128 pcm_buf_ctrl_t buf_ctrl; 00129 pcm_buf_ctrl_t * const p_ctrl = &buf_ctrl; 00130 bool scux_read_enable = false; 00131 AUD_MAIL_ID mail_type; 00132 uint32_t mail_param[MAIL_PARAM_NUM]; 00133 bool result; 00134 AUD_CbDataOut cb_data_out; 00135 uint32_t i; 00136 uint32_t buf_id; 00137 int32_t *p_buf; 00138 uint32_t byte_cnt; 00139 AUD_CbAudioData cb_audio_data; 00140 static int32_t NC_BSS_SECT pcm_buf[PCM_BUF_NUM][TOTAL_SAMPLE_NUM]; 00141 static TLV320_RBSP audio(P10_13, I2C_SDA, I2C_SCL, P4_4, P4_5, P4_7, 00142 P4_6, AUDIO_INT_LEVEL, AUDIO_WRITE_NUM, AUDIO_READ_NUM); 00143 00144 UNUSED_ARG(argument); 00145 00146 /* Initializes the control data of PCM buffer. */ 00147 init_pcm_buf(p_ctrl); 00148 00149 /* Sets the output of PCM data using TLV320_RBSP. */ 00150 (void) audio.format(DEC_OUTPUT_BITS_PER_SAMPLE); 00151 (void) audio.frequency(DEC_OUTPUT_SAMPLE_RATE); 00152 audio.power(AUDIO_POWER_MIC_OFF); 00153 while (1) { 00154 result = recv_mail(&mail_type, &mail_param[MAIL_PARAM0], 00155 &mail_param[MAIL_PARAM1], &mail_param[MAIL_PARAM2]); 00156 if (result == true) { 00157 switch (mail_type) { 00158 case AUD_MAILID_DATA_OUT: /* Requests the output of PCM data. */ 00159 cb_data_out = (AUD_CbDataOut)mail_param[MAIL_DATA_OUT_CB]; 00160 if (scux_read_enable != true) { 00161 scux_read_enable = true; 00162 result = true; 00163 for (i = 0; (i < p_ctrl->pcm_buf_remain_cnt) && (result == true); i++) { 00164 buf_id = (p_ctrl->pcm_buf_index + i) % PCM_BUF_NUM; 00165 result = read_scux(&pcm_buf[buf_id], buf_id); 00166 } 00167 if (result == true) { 00168 p_ctrl->output_trg_cnt = OUTPUT_START_TRIGGER; 00169 } 00170 } else { 00171 result = false; 00172 } 00173 cb_data_out(result); 00174 break; 00175 case AUD_MAILID_ZERO_OUT: /* Requests the output of zero data. */ 00176 scux_read_enable = false; 00177 break; 00178 case AUD_MAILID_SCUX_READ_FIN: /* Finished the reading process of SCUX. */ 00179 buf_id = mail_param[MAIL_SCUX_READ_BUF_INDEX]; 00180 byte_cnt = mail_param[MAIL_SCUX_READ_BYTE_NUM]; 00181 if ((buf_id < PCM_BUF_NUM) && (byte_cnt <= sizeof(pcm_buf[0]))) { 00182 if (byte_cnt < sizeof(pcm_buf[0])) { 00183 /* End of stream */ 00184 /* Fills the remain area of PCM buffer with 0. */ 00185 p_buf = &pcm_buf[buf_id][byte_cnt/sizeof(pcm_buf[0][0])]; 00186 (void) memset(p_buf, 0, sizeof(pcm_buf[0]) - byte_cnt); 00187 p_ctrl->output_trg_cnt = OUTPUT_UPDATE_TRIGGER; 00188 } 00189 p_ctrl->pcm_stock_cnt++; 00190 if (p_ctrl->pcm_stock_cnt >= p_ctrl->output_trg_cnt) { 00191 /* Starts the output of PCM data. */ 00192 result = true; 00193 for (i = 0; (i < p_ctrl->pcm_stock_cnt) && (result == true); i++) { 00194 buf_id = (p_ctrl->pcm_buf_index + i) % PCM_BUF_NUM; 00195 result = write_audio(&audio, &pcm_buf[buf_id], buf_id); 00196 if (result == true) { 00197 p_ctrl->pcm_buf_remain_cnt--; 00198 } 00199 } 00200 if (result != true) { 00201 /* Unexpected cases : Output error message to PC */ 00202 (void) dsp_notify_print_string(ERR_MSG_TLV320_RBSP_WRITE); 00203 } 00204 p_ctrl->pcm_buf_index = 00205 (p_ctrl->pcm_buf_index + p_ctrl->pcm_stock_cnt) % PCM_BUF_NUM; 00206 p_ctrl->pcm_stock_cnt = 0u; 00207 p_ctrl->output_trg_cnt = OUTPUT_UPDATE_TRIGGER; 00208 } 00209 } else { 00210 /* Unexpected cases : This is fail-safe processing. */ 00211 scux_read_enable = false; 00212 } 00213 break; 00214 case AUD_MAILID_PCM_OUT_FIN: /* Finished the output of data. */ 00215 p_ctrl->pcm_buf_remain_cnt++; 00216 if ((int32_t)mail_param[MAIL_PCM_OUT_RESULT] == true) { 00217 buf_id = mail_param[MAIL_PCM_OUT_BUF_INDEX]; 00218 if (scux_read_enable == true) { 00219 (void) read_scux(&pcm_buf[buf_id], buf_id); 00220 } else { 00221 (void) memset(&pcm_buf[buf_id], 0, sizeof(pcm_buf[0])); 00222 } 00223 } else { 00224 /* Unexpected cases : Output error message to PC */ 00225 (void) dsp_notify_print_string(ERR_MSG_TLV320_RBSP_WRITE); 00226 } 00227 break; 00228 case AUD_MAILID_GET_AUDIO: 00229 cb_audio_data = (AUD_CbAudioData)mail_param[MAIL_GET_AUDIO_CB]; 00230 if (cb_audio_data != NULL) { 00231 if (p_ctrl->pcm_buf_index > 0u) { 00232 buf_id = p_ctrl->pcm_buf_index - 1u; 00233 } else { 00234 buf_id = PCM_BUF_NUM - 1u; 00235 } 00236 cb_audio_data(true, (int16_t*)mail_param[MAIL_GET_AUDIO_BUF], 00237 mail_param[MAIL_GET_AUDIO_NUM], pcm_buf[buf_id], sizeof(pcm_buf[0])/sizeof(pcm_buf[0][0])); 00238 } 00239 break; 00240 default: 00241 /* Unexpected cases : Output error message to PC */ 00242 (void) dsp_notify_print_string(ERR_MSG_RECV_ILLEGAL_MAIL); 00243 break; 00244 } 00245 } 00246 } 00247 } 00248 00249 bool aud_req_data_out(const AUD_CbDataOut p_cb) 00250 { 00251 bool ret = false; 00252 00253 if (p_cb != NULL) { 00254 ret = send_mail(AUD_MAILID_DATA_OUT, (uint32_t)p_cb, MAIL_PARAM_NON, MAIL_PARAM_NON); 00255 } 00256 return ret; 00257 } 00258 00259 bool aud_req_zero_out(void) 00260 { 00261 bool ret = false; 00262 00263 ret = send_mail(AUD_MAILID_ZERO_OUT, MAIL_PARAM_NON, MAIL_PARAM_NON, MAIL_PARAM_NON); 00264 return ret; 00265 } 00266 00267 bool aud_get_audio_data(const AUD_CbAudioData p_cb, int16_t * const p_buf, const uint32_t buf_num) 00268 { 00269 bool ret = false; 00270 00271 if ((p_cb != NULL) && (p_buf != NULL) && (buf_num > 0u)) { 00272 ret = send_mail(AUD_MAILID_GET_AUDIO, (uint32_t)p_cb, (uint32_t)p_buf, (uint32_t)buf_num); 00273 } 00274 return ret; 00275 } 00276 00277 /** Initialises the control data of PCM buffer 00278 * 00279 * @param p_ctrl Pointer to the control data of PCM buffer. 00280 */ 00281 static void init_pcm_buf(pcm_buf_ctrl_t * const p_ctrl) 00282 { 00283 if (p_ctrl != NULL) { 00284 p_ctrl->pcm_buf_index = 0u; 00285 p_ctrl->pcm_buf_remain_cnt = PCM_BUF_NUM; 00286 p_ctrl->pcm_stock_cnt = 0u; 00287 p_ctrl->output_trg_cnt = OUTPUT_START_TRIGGER; 00288 } 00289 } 00290 00291 /** Gets PCM data from SCUX driver 00292 * 00293 * @param p_buf Pointer to PCM buffer array to store the data. 00294 * @param buf_id The control ID of PCM buffer. 00295 * 00296 * @returns 00297 * Results of process. true is success. false is failure. 00298 */ 00299 static bool read_scux(int32_t (* const p_buf)[TOTAL_SAMPLE_NUM], const uint32_t buf_id) 00300 { 00301 bool ret = false; 00302 rbsp_data_conf_t cb_conf = { 00303 &read_callback, 00304 NULL 00305 }; 00306 00307 if ((p_buf != NULL) && (buf_id < PCM_BUF_NUM)) { 00308 cb_conf.p_app_data = (void *)buf_id; 00309 ret = dec_scux_read(p_buf, sizeof(p_buf[0]), &cb_conf); 00310 } 00311 return ret; 00312 } 00313 00314 /** Writes PCM data to TLV320_RBSP driver 00315 * 00316 * @param p_buf Pointer to PCM buffer array. 00317 * @param buf_id The control ID of PCM buffer. 00318 * 00319 * @returns 00320 * Results of process. true is success. false is failure. 00321 */ 00322 static bool write_audio(TLV320_RBSP * const p_audio, int32_t (* const p_buf)[TOTAL_SAMPLE_NUM], const uint32_t buf_id) 00323 { 00324 bool ret = false; 00325 int32_t result; 00326 rbsp_data_conf_t cb_conf = { 00327 &pcm_out_callback, 00328 NULL 00329 }; 00330 00331 if ((p_audio != NULL) && (p_buf != NULL) && (buf_id < PCM_BUF_NUM)) { 00332 cb_conf.p_app_data = (void *)buf_id; 00333 result = p_audio->write(p_buf, sizeof(p_buf[0]), &cb_conf); 00334 if (result == ESUCCESS) { 00335 ret = true; 00336 } 00337 } 00338 return ret; 00339 } 00340 00341 /** Callback function of SCUX driver 00342 * 00343 * @param p_data Pointer to PCM byffer array. 00344 * @param result Result of the process. 00345 * @param p_app_data The control ID of PCM buffer. 00346 */ 00347 static void read_callback(void * p_data, int32_t result, void * p_app_data) 00348 { 00349 const uint32_t buf_id = (uint32_t)p_app_data; 00350 uint32_t read_byte; 00351 bool flag_result; 00352 00353 UNUSED_ARG(p_data); 00354 if (result > 0) { 00355 flag_result = true; 00356 read_byte = (uint32_t)result; 00357 } else { 00358 flag_result = false; 00359 read_byte = 0u; 00360 } 00361 (void) send_mail(AUD_MAILID_SCUX_READ_FIN, (uint32_t)flag_result, buf_id, read_byte); 00362 } 00363 00364 /** Callback function of TLV320_RBSP driver 00365 * 00366 * @param p_data Pointer to PCM byffer array. 00367 * @param result Result of the process. 00368 * @param p_app_data The control ID of PCM buffer. 00369 */ 00370 static void pcm_out_callback(void * p_data, int32_t result, void * p_app_data) 00371 { 00372 const uint32_t buf_id = (uint32_t)p_app_data; 00373 bool flag_result; 00374 00375 UNUSED_ARG(p_data); 00376 if (result > 0) { 00377 flag_result = true; 00378 } else { 00379 flag_result = false; 00380 } 00381 (void) send_mail(AUD_MAILID_PCM_OUT_FIN, (uint32_t)flag_result, buf_id, MAIL_PARAM_NON); 00382 } 00383 00384 /** Sends the mail to Decode thread 00385 * 00386 * @param mail_id Mail ID 00387 * @param param0 Parameter 0 of this mail 00388 * @param param1 Parameter 1 of this mail 00389 * @param param2 Parameter 2 of this mail 00390 * 00391 * @returns 00392 * Results of process. true is success. false is failure. 00393 */ 00394 static bool send_mail(const AUD_MAIL_ID mail_id, const uint32_t param0, 00395 const uint32_t param1, const uint32_t param2) 00396 { 00397 bool ret = false; 00398 osStatus stat; 00399 aud_mail_t * const p_mail = mail_box.alloc(); 00400 00401 if (p_mail != NULL) { 00402 p_mail->mail_id = mail_id; 00403 p_mail->param[MAIL_PARAM0] = param0; 00404 p_mail->param[MAIL_PARAM1] = param1; 00405 p_mail->param[MAIL_PARAM2] = param2; 00406 stat = mail_box.put(p_mail); 00407 if (stat == osOK) { 00408 ret = true; 00409 } else { 00410 (void) mail_box.free(p_mail); 00411 } 00412 } 00413 return ret; 00414 } 00415 00416 /** Receives the mail to Decode thread 00417 * 00418 * @param p_mail_id Pointer to the variable to store the mail ID 00419 * @param p_param0 Pointer to the variable to store the parameter 0 of this mail 00420 * @param p_param1 Pointer to the variable to store the parameter 1 of this mail 00421 * @param p_param2 Pointer to the variable to store the parameter 2 of this mail 00422 * 00423 * @returns 00424 * Results of process. true is success. false is failure. 00425 */ 00426 static bool recv_mail(AUD_MAIL_ID * const p_mail_id, uint32_t * const p_param0, 00427 uint32_t * const p_param1, uint32_t * const p_param2) 00428 { 00429 bool ret = false; 00430 osEvent evt; 00431 aud_mail_t *p_mail; 00432 00433 if ((p_mail_id != NULL) && (p_param0 != NULL) && 00434 (p_param1 != NULL) && (p_param2 != NULL)) { 00435 evt = mail_box.get(); 00436 if (evt.status == osEventMail) { 00437 p_mail = (aud_mail_t *)evt.value.p; 00438 if (p_mail != NULL) { 00439 *p_mail_id = p_mail->mail_id; 00440 *p_param0 = p_mail->param[MAIL_PARAM0]; 00441 *p_param1 = p_mail->param[MAIL_PARAM1]; 00442 *p_param2 = p_mail->param[MAIL_PARAM2]; 00443 ret = true; 00444 } 00445 (void) mail_box.free(p_mail); 00446 } 00447 } 00448 return ret; 00449 }
Generated on Tue Jul 12 2022 19:32:28 by 1.7.2