Daiki Kato / Mbed OS GR-Boards_Audio_Recoder

Dependencies:   mbed-os-lychee

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 #include "mbed.h"
00002 #include "SdUsbConnect.h"
00003 #include "AUDIO_GRBoard.h"
00004 
00005 #define MOUNT_NAME             "storage"
00006 #define FINE_PATH              "/"MOUNT_NAME"/wav_rec.wav"
00007 
00008 #define SAMPLE_RATE            (8000)
00009 #define AUDIO_IN_BUF_SIZE      (2048)
00010 #define AUDIO_IN_BUF_NUM       (16)
00011 #define AUDIO_OUT_BUF_SIZE     (2048)
00012 #define AUDIO_OUT_BUF_NUM      (8)
00013 #define AUDIO_OUT_WAIT         ((AUDIO_OUT_BUF_SIZE * AUDIO_OUT_BUF_NUM / 4) * 1000 / SAMPLE_RATE)
00014 
00015 #define INFO_TYPE_OPEN         (0)
00016 #define INFO_TYPE_CLOSE        (1)
00017 #define INFO_TYPE_WRITE_DATA   (2)
00018 
00019 AUDIO_GRBoard audio(0x80, AUDIO_OUT_BUF_NUM - 1, AUDIO_IN_BUF_NUM); // I2S Codec
00020 DigitalOut  led_rec(LED_RED);
00021 DigitalOut  led_play(LED_GREEN);
00022 InterruptIn button_0(USER_BUTTON0);
00023 #if defined(TARGET_GR_LYCHEE)
00024 InterruptIn button_1(USER_BUTTON1);
00025 #endif
00026 static bool play_req = false;
00027 
00028 typedef struct {
00029     uint32_t info_type;
00030     void *   p_data;
00031     int32_t  result;
00032 } mail_t;
00033 Mail<mail_t, (AUDIO_IN_BUF_NUM + 2)> mail_box;
00034 
00035 static Thread audioInTask(osPriorityNormal, 1024 * 8);
00036 //4 bytes aligned! No cache memory
00037 #if defined(__ICCARM__)
00038 #pragma data_alignment=4
00039 static uint8_t audio_in_buf[AUDIO_IN_BUF_NUM][AUDIO_IN_BUF_SIZE]@ ".mirrorram";
00040 #pragma data_alignment=4
00041 static uint8_t audio_out_buf[AUDIO_OUT_BUF_NUM][AUDIO_OUT_BUF_SIZE]@ ".mirrorram";
00042 #else
00043 static uint8_t audio_in_buf[AUDIO_IN_BUF_NUM][AUDIO_IN_BUF_SIZE]__attribute((section("NC_BSS"),aligned(4)));
00044 static uint8_t audio_out_buf[AUDIO_OUT_BUF_NUM][AUDIO_OUT_BUF_SIZE]__attribute((section("NC_BSS"),aligned(4)));
00045 #endif
00046 
00047 // wav file header
00048 static const char wav_header_tbl[] = {
00049     0x52,0x49,0x46,0x46,0x00,0x00,0x00,0x00,0x57,0x41,0x56,0x45,0x66,0x6D,0x74,0x20,
00050     0x10,0x00,0x00,0x00,0x01,0x00,0x02,0x00,0x80,0xBB,0x00,0x00,0x00,0xEE,0x02,0x00,
00051     0x04,0x00,0x10,0x00,0x64,0x61,0x74,0x61,0x00,0x00,0x00,0x00
00052 };
00053 
00054 #if MBED_CONF_APP_LCD
00055 #include "EasyAttach_CameraAndLCD.h"
00056 
00057 #define FRAME_BUFFER_STRIDE    (((LCD_PIXEL_WIDTH * 2) + 31u) & ~31u)
00058 #define FRAME_BUFFER_HEIGHT    (LCD_PIXEL_HEIGHT)
00059 #if defined(__ICCARM__)
00060 #pragma data_alignment=32
00061 static uint8_t user_frame_buffer0[FRAME_BUFFER_STRIDE * FRAME_BUFFER_HEIGHT]@ ".mirrorram";
00062 #else
00063 static uint8_t user_frame_buffer0[FRAME_BUFFER_STRIDE * FRAME_BUFFER_HEIGHT]__attribute((section("NC_BSS"),aligned(32)));
00064 #endif
00065 DisplayBase Display;
00066 
00067 static void Start_LCD_Display(void) {
00068     DisplayBase::rect_t rect;
00069 
00070     memset(user_frame_buffer0, 0xFF, sizeof(user_frame_buffer0));
00071 
00072     rect.vs = 0;
00073     rect.vw = LCD_PIXEL_HEIGHT;
00074     rect.hs = 0;
00075     rect.hw = LCD_PIXEL_WIDTH;
00076     Display.Graphics_Read_Setting(
00077         DisplayBase::GRAPHICS_LAYER_0,
00078         (void *)user_frame_buffer0,
00079         FRAME_BUFFER_STRIDE,
00080         DisplayBase::GRAPHICS_FORMAT_RGB565,
00081         DisplayBase::WR_RD_WRSWA_32_16BIT,
00082         &rect
00083     );
00084     Display.Graphics_Start(DisplayBase::GRAPHICS_LAYER_0);
00085 
00086     Thread::wait(50);
00087     EasyAttach_LcdBacklight(true);
00088 }
00089 
00090 static void disp_audio_wave(int16_t * p_data, int32_t size, uint32_t color) {
00091     uint16_t * p_bottom_left_pos = (uint16_t *)&user_frame_buffer0[FRAME_BUFFER_STRIDE * (FRAME_BUFFER_HEIGHT - 1)];
00092     uint16_t * p_frame_buf;
00093     uint32_t x = 0;
00094     uint32_t data_pos;
00095     uint32_t data_pos_last = ((p_data[0] + 0x8000ul) >> 8) + 8;
00096     int loop_num;
00097 
00098     if (size < 0) {
00099         return;
00100     }
00101 
00102     memset(user_frame_buffer0, 0xFF, sizeof(user_frame_buffer0));
00103     for (int i = 0; i < size; i += 2) {
00104         data_pos = ((p_data[i] + 0x8000ul) >> 8) + 8;
00105         p_frame_buf = &p_bottom_left_pos[x];
00106 
00107         if (data_pos == data_pos_last) {
00108             loop_num = 3;
00109             p_frame_buf -= ((data_pos - 1) * LCD_PIXEL_WIDTH);
00110         } else if (data_pos > data_pos_last) {
00111             loop_num = data_pos - data_pos_last + 2;
00112             p_frame_buf -= (data_pos_last * LCD_PIXEL_WIDTH);
00113         } else {
00114             loop_num = data_pos_last - data_pos + 2;
00115             p_frame_buf -= ((data_pos - 1) * LCD_PIXEL_WIDTH);
00116         }
00117 
00118         for (int j = 0; j < loop_num; j++) {
00119             *p_frame_buf = color;
00120             p_frame_buf -= LCD_PIXEL_WIDTH;
00121         }
00122         data_pos_last = data_pos;
00123 
00124         x++;
00125         if (x >= LCD_PIXEL_WIDTH) {
00126             break;
00127         }
00128     }
00129 }
00130 
00131 static void callback_audio_write_end(void * p_data, int32_t result, void * p_app_data) {
00132     disp_audio_wave((int16_t *)p_data, result / 2, 0x07E0); // Green
00133 }
00134 #endif // MBED_CONF_APP_LCD
00135 
00136 static void send_mail(uint32_t info_type, void * p_data, int32_t result) {
00137     mail_t *mail = mail_box.alloc();
00138 
00139     if (mail != NULL) {
00140         mail->info_type = info_type;
00141         mail->p_data    = p_data;
00142         mail->result    = result;
00143         mail_box.put(mail);
00144     }
00145 }
00146 
00147 static void rec_start(void) {
00148     send_mail(INFO_TYPE_OPEN, NULL, 0);
00149 }
00150 
00151 static void rec_stop(void) {
00152     send_mail(INFO_TYPE_CLOSE, NULL, 0);
00153 }
00154 
00155 static void play_start(void) {
00156     play_req = true;
00157 }
00158 
00159 static void callback_audio_read_end(void * p_data, int32_t result, void * p_app_data) {
00160 #if MBED_CONF_APP_LCD
00161     if (led_play == 0) {
00162         uint32_t color;
00163 
00164         if (led_rec == 0) {
00165             color = 0x001F; // Blue
00166         } else {
00167             color = 0xF800; // Red
00168         }
00169         disp_audio_wave((int16_t *)p_data, result / 2, color);
00170     }
00171 #endif
00172     send_mail(INFO_TYPE_WRITE_DATA, p_data, result);
00173 }
00174 
00175 static void wire_data_4byte(uint32_t data, FILE * fp) {
00176     char work_buf[4];
00177 
00178     work_buf[0] = (uint8_t)(data >> 0);
00179     work_buf[1] = (uint8_t)(data >> 8);
00180     work_buf[2] = (uint8_t)(data >> 16);
00181     work_buf[3] = (uint8_t)(data >> 24);
00182     fwrite(work_buf, sizeof(char), 4, fp);
00183 }
00184 
00185 void audio_in_task(void) {
00186     FILE * wav_fp = NULL;
00187     uint32_t pcm_size = 0;
00188     rbsp_data_conf_t audio_read_data  = {&callback_audio_read_end, NULL};
00189 
00190     // Read buffer setting
00191     for (uint32_t i = 0; i < AUDIO_IN_BUF_NUM; i++) {
00192         if (audio.read(audio_in_buf[i], AUDIO_IN_BUF_SIZE, &audio_read_data) < 0) {
00193             printf("read error\n");
00194         }
00195     }
00196 
00197     while (1) {
00198         osEvent evt = mail_box.get();
00199         if (evt.status == osEventMail) {
00200             mail_t *mail = (mail_t *)evt.value.p;
00201 
00202             switch (mail->info_type) {
00203                 case INFO_TYPE_OPEN:
00204                     wav_fp = fopen(FINE_PATH, "wb");
00205                     if (wav_fp != NULL) {
00206                         led_rec  = 1;  // REC start
00207                         pcm_size = 0;
00208                         fwrite(wav_header_tbl, sizeof(char), sizeof(wav_header_tbl), wav_fp);
00209                     }
00210                     break;
00211 
00212                 case INFO_TYPE_CLOSE:
00213                     if (wav_fp != NULL) {
00214                         // Set "RIFF" ChunkSize
00215                         fseek(wav_fp, 4, SEEK_SET);
00216                         wire_data_4byte(sizeof(wav_header_tbl) - 8 + pcm_size, wav_fp);
00217                         // Set SampleRate
00218                         fseek(wav_fp, 24, SEEK_SET);
00219                         wire_data_4byte(SAMPLE_RATE, wav_fp);
00220                         // Set ByteRate
00221                         wire_data_4byte(SAMPLE_RATE * 2 * 2, wav_fp);
00222                         // Set "data" ChunkSize
00223                         fseek(wav_fp, 40, SEEK_SET);
00224                         wire_data_4byte(pcm_size, wav_fp);
00225                         fclose(wav_fp);
00226                         wav_fp = NULL;
00227                         led_rec = 0;  // REC end
00228 #if !defined(TARGET_GR_LYCHEE)
00229                         play_start();
00230 #endif
00231                     }
00232                     break;
00233 
00234                 case INFO_TYPE_WRITE_DATA:
00235                     if ((mail->result > 0) && (wav_fp != NULL)) {
00236                         pcm_size += mail->result;
00237                         fwrite(mail->p_data, sizeof(char), mail->result, wav_fp);
00238                     }
00239                     audio.read(mail->p_data, AUDIO_IN_BUF_SIZE, &audio_read_data);     // Resetting read buffer
00240                     break;
00241 
00242                 default:
00243                     // do nothing
00244                     break;
00245             }
00246             mail_box.free(mail);
00247         }
00248     }
00249 }
00250 
00251 int main() {
00252 #if MBED_CONF_APP_LCD
00253     rbsp_data_conf_t audio_write_data = {&callback_audio_write_end, NULL};
00254 
00255     EasyAttach_Init(Display);
00256     Start_LCD_Display();
00257 #else
00258     rbsp_data_conf_t audio_write_data = {NULL, NULL};
00259 #endif
00260 
00261     // Microphone
00262     audio.micVolume(0.50);
00263     audio.outputVolume(0.50, 0.50);
00264     audio.power(true);
00265     audio.frequency(SAMPLE_RATE);
00266 
00267     SdUsbConnect storage(MOUNT_NAME);
00268     audioInTask.start(callback(audio_in_task));
00269 
00270     // button setting
00271     button_0.fall(&rec_start);
00272     button_0.rise(&rec_stop);
00273 #if defined(TARGET_GR_LYCHEE)
00274     button_1.fall(&play_start);
00275 #endif
00276 
00277     while (1) {
00278         storage.wait_connect();
00279 
00280         // Audio playback
00281         if (play_req != false) {
00282             while (led_rec == 1) {
00283                 Thread::wait(10); // Wait write end
00284             }
00285 
00286             size_t read_size = AUDIO_OUT_BUF_SIZE;
00287             uint32_t index = 0;
00288 
00289             play_req = false;
00290             led_play = 1;
00291             FILE * fp_rb = fopen(FINE_PATH, "rb");
00292             if (fp_rb != NULL) {
00293                 fseek(fp_rb, sizeof(wav_header_tbl), SEEK_SET);
00294                 while (read_size == AUDIO_OUT_BUF_SIZE) {
00295                     read_size = fread(audio_out_buf[index], sizeof(char), AUDIO_OUT_BUF_SIZE, fp_rb);
00296                     audio.write(audio_out_buf[index], read_size, &audio_write_data);
00297                     index++;
00298                     if (index >= AUDIO_OUT_BUF_NUM) {
00299                         index = 0;
00300                     }
00301                 }
00302                 fclose(fp_rb);
00303                 Thread::wait(AUDIO_OUT_WAIT);
00304             }
00305             led_play = 0;
00306         }
00307         Thread::wait(100);
00308     }
00309 }