0.0
Dependencies: DISCO-F746NG_BLOCK_DEVICE_WITH_FAT_FILESYSTEM_ON_SDCARD SDRAM_DISCO_F746NG BSP_DISCO_F746NG BD_SD_DISCO_F746NG AUDIO_DISCO_F746NG
main.cpp
- Committer:
- KKBanana
- Date:
- 2019-09-05
- Revision:
- 4:ce6b2364970d
- Parent:
- 3:7f991a3d4e71
File content as of revision 4:ce6b2364970d:
/* Example file of using SD/MMC Block device Library for MBED-OS * Copyright 2017 Roy Krikke * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include "mbed.h" #include "FATFileSystem.h" #include "SDBlockDeviceDISCOF746NG.h" #include "AUDIO_DISCO_F746NG.h" #include "SDRAM_DISCO_F746NG.h" #include <stdio.h> #include <stdlib.h> #include <errno.h> #define AUDIO_IN_PCM_BUFFER_SIZE 4*2304 /* buffer size in half-word */ typedef enum { BUFFER_EMPTY = 0, BUFFER_FULL, }WR_BUFFER_StateTypeDef; typedef struct { uint32_t ChunkID; /* 0 */ uint32_t FileSize; /* 4 */ uint32_t FileFormat; /* 8 */ uint32_t SubChunk1ID; /* 12 */ uint32_t SubChunk1Size; /* 16*/ uint16_t AudioFormat; /* 20 */ uint16_t NbrChannels; /* 22 */ uint32_t SampleRate; /* 24 */ uint32_t ByteRate; /* 28 */ uint16_t BlockAlign; /* 32 */ uint16_t BitPerSample; /* 34 */ uint32_t SubChunk2ID; /* 36 */ uint32_t SubChunk2Size; /* 40 */ } WAVE_FormatTypeDef; typedef struct { uint16_t pcm_buff[AUDIO_IN_PCM_BUFFER_SIZE]; uint32_t pcm_ptr; WR_BUFFER_StateTypeDef wr_state; uint32_t offset; uint32_t fptr; }AUDIO_IN_BufferTypeDef; static uint32_t WavProcess_EncInit(uint32_t Freq, uint8_t* pHeader); static uint32_t WavProcess_HeaderInit(uint8_t* pHeader, WAVE_FormatTypeDef* pWaveFormatStruct); // Instantiate the Block Device for sd card on DISCO-F746NG SDBlockDeviceDISCOF746NG bd; AUDIO_DISCO_F746NG audio; // audio IN_OUT buffer is stored in the SDRAM, SDRAM needs to be initialized and FMC enabled SDRAM_DISCO_F746NG sdram; FATFileSystem fs ("fs"); //static AUDIO_IN_BufferTypeDef BufferCtl; static __IO uint32_t uwVolume = 100; extern WAVE_FormatTypeDef WaveFormat; extern FIL WavFile; //static uint32_t display_update = 1; static uint32_t WavProcess_EncInit(uint32_t Freq, uint8_t *pHeader) { /* Initialize the encoder structure */ WaveFormat.SampleRate = Freq; /* Audio sampling frequency */ WaveFormat.NbrChannels = 2; /* Number of channels: 1:Mono or 2:Stereo */ WaveFormat.BitPerSample = 16; /* Number of bits per sample (16, 24 or 32) */ WaveFormat.FileSize = 0x001D4C00; /* Total length of useful audio data (payload) */ WaveFormat.SubChunk1Size = 44; /* The file header chunk size */ WaveFormat.ByteRate = (WaveFormat.SampleRate * \ (WaveFormat.BitPerSample/8) * \ WaveFormat.NbrChannels); /* Number of bytes per second (sample rate * block align) */ WaveFormat.BlockAlign = WaveFormat.NbrChannels * \ (WaveFormat.BitPerSample/8); /* channels * bits/sample / 8 */ /* Parse the wav file header and extract required information */ if(WavProcess_HeaderInit(pHeader, &WaveFormat)) { return 1; } return 0; } static uint32_t WavProcess_HeaderInit(uint8_t* pHeader, WAVE_FormatTypeDef* pWaveFormatStruct) { /* Write chunkID, must be 'RIFF' ------------------------------------------*/ pHeader[0] = 'R'; pHeader[1] = 'I'; pHeader[2] = 'F'; pHeader[3] = 'F'; /* Write the file length ---------------------------------------------------*/ /* The sampling time: this value will be written back at the end of the recording operation. Example: 661500 Btyes = 0x000A17FC, byte[7]=0x00, byte[4]=0xFC */ pHeader[4] = 0x00; pHeader[5] = 0x4C; pHeader[6] = 0x1D; pHeader[7] = 0x00; /* Write the file format, must be 'WAVE' -----------------------------------*/ pHeader[8] = 'W'; pHeader[9] = 'A'; pHeader[10] = 'V'; pHeader[11] = 'E'; /* Write the format chunk, must be'fmt ' -----------------------------------*/ pHeader[12] = 'f'; pHeader[13] = 'm'; pHeader[14] = 't'; pHeader[15] = ' '; /* Write the length of the 'fmt' data, must be 0x10 ------------------------*/ pHeader[16] = 0x10; pHeader[17] = 0x00; pHeader[18] = 0x00; pHeader[19] = 0x00; /* Write the audio format, must be 0x01 (PCM) ------------------------------*/ pHeader[20] = 0x01; pHeader[21] = 0x00; /* Write the number of channels, ie. 0x01 (Mono) ---------------------------*/ pHeader[22] = pWaveFormatStruct->NbrChannels; pHeader[23] = 0x00; /* Write the Sample Rate in Hz ---------------------------------------------*/ /* Write Little Endian ie. 8000 = 0x00001F40 => byte[24]=0x40, byte[27]=0x00*/ pHeader[24] = (uint8_t)((pWaveFormatStruct->SampleRate & 0xFF)); pHeader[25] = (uint8_t)((pWaveFormatStruct->SampleRate >> 8) & 0xFF); pHeader[26] = (uint8_t)((pWaveFormatStruct->SampleRate >> 16) & 0xFF); pHeader[27] = (uint8_t)((pWaveFormatStruct->SampleRate >> 24) & 0xFF); /* Write the Byte Rate -----------------------------------------------------*/ pHeader[28] = (uint8_t)((pWaveFormatStruct->ByteRate & 0xFF)); pHeader[29] = (uint8_t)((pWaveFormatStruct->ByteRate >> 8) & 0xFF); pHeader[30] = (uint8_t)((pWaveFormatStruct->ByteRate >> 16) & 0xFF); pHeader[31] = (uint8_t)((pWaveFormatStruct->ByteRate >> 24) & 0xFF); /* Write the block alignment -----------------------------------------------*/ pHeader[32] = pWaveFormatStruct->BlockAlign; pHeader[33] = 0x00; /* Write the number of bits per sample -------------------------------------*/ pHeader[34] = pWaveFormatStruct->BitPerSample; pHeader[35] = 0x00; /* Write the Data chunk, must be 'data' ------------------------------------*/ pHeader[36] = 'd'; pHeader[37] = 'a'; pHeader[38] = 't'; pHeader[39] = 'a'; /* Write the number of sample data -----------------------------------------*/ /* This variable will be written back at the end of the recording operation */ pHeader[40] = 0x00; pHeader[41] = 0x4C; pHeader[42] = 0x1D; pHeader[43] = 0x00; /* Return 0 if all operations are OK */ return 0; } void return_error (int ret_val) { if(ret_val) printf ("Failure. %d\r\n", ret_val); else printf ("done.\r\n"); } void errno_error (void* ret_val) { if(ret_val == NULL) printf (" Failure. %d \r\n", errno); else printf (" done.\r\n"); } typedef enum { BUFFER_OFFSET_NONE = 0, BUFFER_OFFSET_HALF = 1, BUFFER_OFFSET_FULL = 2, } BUFFER_StateTypeDef; #define AUDIO_BLOCK_SIZE ((uint32_t)12800) #define AUDIO_BUFFER_IN SDRAM_DEVICE_ADDR /* In SDRAM */ __IO uint32_t audio_rec_buffer_state = BUFFER_OFFSET_NONE; static uint8_t SetSysClock_PLL_HSE_200MHz(); int main () { Serial pc (SERIAL_TX, SERIAL_RX); SetSysClock_PLL_HSE_200MHz(); pc.baud(9600); printf("Start\n"); int error = 0; error = FATFileSystem::format(&bd); return_error(error); error = fs.mount(&bd); return_error(error); FILE* fd; int filenum = 0,filecount = 0; char filenums[1000]; memset((uint16_t*)AUDIO_BUFFER_IN, 0, AUDIO_BLOCK_SIZE*2); audio_rec_buffer_state = BUFFER_OFFSET_NONE; audio.IN_Record((uint16_t*)AUDIO_BUFFER_IN, AUDIO_BLOCK_SIZE); uint8_t pHeaderBuff[44]; while(true) { if(filecount == 0) { sprintf(filenums,"/fs/%d.wav",filenum++); fd = fopen(filenums, "wb"); errno_error(fd); WavProcess_EncInit(DEFAULT_AUDIO_IN_FREQ, pHeaderBuff); fwrite(pHeaderBuff,sizeof(uint8_t), 44,fd); } BSP_AUDIO_IN_Resume(); while(audio_rec_buffer_state == BUFFER_OFFSET_HALF) { } audio_rec_buffer_state = BUFFER_OFFSET_NONE; BSP_AUDIO_IN_Pause(); fwrite ((uint16_t *)(AUDIO_BUFFER_IN), 1, AUDIO_BLOCK_SIZE, fd); BSP_AUDIO_IN_Resume(); while(audio_rec_buffer_state == BUFFER_OFFSET_FULL) { } audio_rec_buffer_state = BUFFER_OFFSET_NONE; BSP_AUDIO_IN_Pause(); fwrite ((uint16_t *)(AUDIO_BUFFER_IN + (AUDIO_BLOCK_SIZE)), 1, AUDIO_BLOCK_SIZE, fd); if(filecount++ == 100) { filecount = 0; printf("Closing %d.",filenum-1); fclose(fd); printf(" done.\r\n"); } } } void BSP_AUDIO_IN_TransferComplete_CallBack(void) { audio_rec_buffer_state = BUFFER_OFFSET_FULL; return; } /** * @brief Manages the DMA Half Transfer complete interrupt. * @param None * @retval None */ void BSP_AUDIO_IN_HalfTransfer_CallBack(void) { audio_rec_buffer_state = BUFFER_OFFSET_HALF; return; } static uint8_t SetSysClock_PLL_HSE_200MHz() { RCC_ClkInitTypeDef RCC_ClkInitStruct; RCC_OscInitTypeDef RCC_OscInitStruct; // Enable power clock __PWR_CLK_ENABLE(); // Enable HSE oscillator and activate PLL with HSE as source RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; RCC_OscInitStruct.HSEState = RCC_HSE_ON; /* External xtal on OSC_IN/OSC_OUT */ // Warning: this configuration is for a 25 MHz xtal clock only RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; RCC_OscInitStruct.PLL.PLLM = 25; // VCO input clock = 1 MHz (25 MHz / 25) RCC_OscInitStruct.PLL.PLLN = 400; // VCO output clock = 400 MHz (1 MHz * 400) RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; // PLLCLK = 200 MHz (400 MHz / 2) RCC_OscInitStruct.PLL.PLLQ = 8; // USB clock = 50 MHz (400 MHz / 8) if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { return 0; // FAIL } // Activate the OverDrive to reach the 216 MHz Frequency if (HAL_PWREx_EnableOverDrive() != HAL_OK) { return 0; // FAIL } // Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2 clocks dividers RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2); RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; // 200 MHz RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; // 200 MHz RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4; // 50 MHz RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2; // 100 MHz if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_7) != HAL_OK) { return 0; // FAIL } HAL_RCC_MCOConfig(RCC_MCO1, RCC_MCO1SOURCE_HSE, RCC_MCODIV_4); return 1; // OK }