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
}