SAI_IO class for using CODEC (MW8994) as analog input and output. このライブラリを登録した際のプログラム:「F746_AudioIO_Demo」

Dependencies:   Array_Matrix

Dependents:   F746_SD_WavPlayer F746_SD_GraphicEqualizer_ren0620 Joerg_turbo_ede CW_Decoder_using_FFT_on_DiscoF746NG ... more

SAI_InOut.cpp

Committer:
MikamiUitOpen
Date:
2018-03-12
Revision:
12:61e2c3cc79a3
Parent:
10:eb439bbba0f2

File content as of revision 12:61e2c3cc79a3:

//-----------------------------------------------------------
//  SaiIO class
//      BSP_DISCO_F746NG Rev.9 に合わせて変更
//      InitInput() の内容を一部変更(変更前の部分はコメントアウト)
//
//  2017/09/17, Copyright (c) 2017 MIKAMI, Naoki
//-----------------------------------------------------------

#include "SAI_InOut.hpp"

namespace Mikami
{
    // Constructor
    SaiIO::SaiIO(InOutBoth ioBoth, int size, int fs,
                 uint16_t inputDevice)
        : FS_(fs), IOBOTH_(ioBoth)
    {
        nData_ = size;
        bufferSize_ = (size*2)*2;
        
        if (ioBoth != OUTPUT)
        {
            inBuffer_.SetSize((size*2)*2);
            inOffset_ = 0;
            captured_ = false;
        }
        if (ioBoth != INPUT)
        {
            outBuffer_.SetSize((size*2)*2);
            tmp_.SetSize(size*2);
            tmpIndex_ = 0;
            xferred_ = false;
            ClearBuffer();
        }
        InitCodec(inputDevice);
    }

    // Input start
    void SaiIO::RecordIn()
    {
        if (BSP_AUDIO_IN_Record(inBuffer_, bufferSize_) == AUDIO_ERROR)
            ErrorTrap();
    }

    // Switching input device and run
    void SaiIO::SwitchInputDevice(int sw)
    {
        uint16_t dev = (sw == 0) ?
                        INPUT_DEVICE_DIGITAL_MICROPHONE_2
                      : INPUT_DEVICE_INPUT_LINE_1;
        InitInput(dev);
        ClearBuffer();
        RecordIn();
        if (IOBOTH_ == BOTH) PlayOut();
    }
    
    // If captured, return true
    bool SaiIO::IsCaptured()
    {
        if (!captured_) return false;

        inIndex_ = inOffset_;
        captured_ = false;
        return true;
    }

    void SaiIO::PlayOut()
    {
        ClearBuffer();
        BSP_AUDIO_OUT_SetAudioFrameSlot(CODEC_AUDIOFRAME_SLOT_02);
        if (BSP_AUDIO_OUT_Play(outBuffer_, bufferSize_*AUDIODATA_SIZE)
            == AUDIO_ERROR)
            ErrorTrap();
    }

    // Return true if transfer completion to output
    bool SaiIO::IsXferred()
    {
        if (!xferred_) return false;
        
        tmpIndex_ = 0;
        xferred_ = false;
        return true;
    }

    void SaiIO::Output(int16_t xL, int16_t xR)
    {
        tmp_[tmpIndex_++] = xL; // Left
        tmp_[tmpIndex_++] = xR; // Right
    }

    void SaiIO::ErrorTrap()
    {
        DigitalOut led1(LED1);
        fprintf(stderr, "\r\n#### ERROR ####\r\n");
        while(true)
        {
            led1 = !led1;
            wait_ms(250);
        }
    }   

    // Initialize audio input and output 
    void SaiIO::InitCodec(uint16_t inputDevice)
    {
        if (inputDevice != 0) InitInput(inputDevice);

        if (IOBOTH_ == OUTPUT)
            if (BSP_AUDIO_OUT_Init(OUTPUT_DEVICE_HEADPHONE,
                                   100, FS_) == AUDIO_ERROR)
                ErrorTrap();

        if (IOBOTH_ != OUTPUT) SetInput();
        if (IOBOTH_ != INPUT) SetOutput();
    }

    void SaiIO::InitInput(uint16_t inputDevice)
    {
        int audioInVolume = (inputDevice == INPUT_DEVICE_INPUT_LINE_1) ?
                            70 : 90;
        InputFp = (inputDevice == INPUT_DEVICE_INPUT_LINE_1) ?
                  &SaiIO::InputNormal : &SaiIO::InputReversal;
        if (IOBOTH_ == BOTH)
/*
            if (BSP_AUDIO_IN_OUT_Init(inputDevice, OUTPUT_DEVICE_HEADPHONE,
                                      audioInVolume, FS_) == AUDIO_ERROR)
*/
            if (BSP_AUDIO_IN_OUT_Init(inputDevice, OUTPUT_DEVICE_HEADPHONE,
                                      FS_, DEFAULT_AUDIO_IN_BIT_RESOLUTION,
                                      DEFAULT_AUDIO_IN_CHANNEL_NBR) == AUDIO_ERROR)
                ErrorTrap();

        if (IOBOTH_ == INPUT)
            if (BSP_AUDIO_IN_Init(inputDevice,
                                  audioInVolume, FS_) == AUDIO_ERROR)
                ErrorTrap();
    }

    void SaiIO::SetInput()
    {
        NVIC_SetVector(AUDIO_IN_SAIx_DMAx_IRQ,
                       (uint32_t)AUDIO_IN_SAIx_DMAx_IRQHandler);
    }

    void SaiIO::SetOutput()
    {
        NVIC_SetVector(AUDIO_OUT_SAIx_DMAx_IRQ,
                       (uint32_t)AUDIO_OUT_SAIx_DMAx_IRQHandler);
        BSP_AUDIO_OUT_SetAudioFrameSlot(CODEC_AUDIOFRAME_SLOT_02);
    }

    void SaiIO::ClearBuffer()
    {
        if (IOBOTH_ != OUTPUT)
            for (int n=0; n<bufferSize_; n++) inBuffer_[n] = 0;
        for (int n=0; n<bufferSize_; n++) outBuffer_[n] = 0;
        for (int n=0; n<nData_*2; n++) tmp_[n] = 0;
    }

    // For line input
    void SaiIO::InputNormal(int16_t &xL, int16_t &xR)
    {
        xL = inBuffer_[inIndex_++];
        xR = inBuffer_[inIndex_++];
    }

    // For MEMS microphone input
    void SaiIO::InputReversal(int16_t &xL, int16_t &xR)       
    {
        xR = inBuffer_[inIndex_++];
        xL = inBuffer_[inIndex_++];
    }

    void SaiIO::Captured(int32_t offset)
    {
        captured_ = true;
        inOffset_ = offset;
    }

    void SaiIO::FillBuffer(uint32_t offset)
    {
        int k = offset;
        for (int n=0; n<nData_*2; n++)
             outBuffer_[k++] = tmp_[n];
        xferred_ = true;
    }

    int32_t SaiIO::nData_;
    int32_t SaiIO::bufferSize_;

    __IO bool SaiIO::captured_;
    __IO int32_t SaiIO::inOffset_;

    Array<uint16_t> SaiIO::outBuffer_;
    Array<uint16_t> SaiIO::tmp_;       
    __IO bool SaiIO::xferred_;
}