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

Revision:
0:eade5d3ae0eb
Child:
1:48ed86c8430a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SAI_InOut.cpp	Thu May 05 11:12:45 2016 +0000
@@ -0,0 +1,199 @@
+//-----------------------------------------------------------
+//  SiaIO class
+//  2016/05/05, Copyright (c) 2016 MIKAMI, Naoki
+//-----------------------------------------------------------
+
+#include "SAI_InOut.hpp"
+#include "MyBSP_AUDIO_IN_OUT_Init.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_ = new int16_t[(size*2)*2];
+            inOffset_ = 0;
+            captured_ = false;
+        }
+        outBuffer_ = new int16_t[(size*2)*2];
+        tmp_ = new int16_t[size*2];
+        tmpIndex_ = 0;
+        xferred_ = false;
+
+        ClearBuffer();
+        InitCodec(inputDevice);
+    }
+
+    SaiIO::~SaiIO()
+    {
+        delete[] tmp_;
+        delete[] outBuffer_;
+        if (IOBOTH_ != OUTPUT) delete[] inBuffer_;
+    }
+
+    // Stop audio input
+    void SaiIO::StopAudioIn()
+    {
+        if (BSP_AUDIO_IN_Stop(CODEC_PDWN_SW) == 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;
+        InitCodec(dev);
+    }
+    
+    // If captured, return true
+    bool SaiIO::IsCaptured()
+    {
+        if (!captured_) return false;
+
+        inIndex_ = inOffset_;
+        return true;
+    }
+
+    // Input from input buffer
+    void SaiIO::Input(int16_t &xL, int16_t &xR)
+    {
+        xL = inBuffer_[inIndex_++];
+        xR = inBuffer_[inIndex_++];
+    }
+
+    bool SaiIO::IsXferred()
+    {
+        if (!xferred_) return false;
+        
+        tmpIndex_ = 0;
+        return true;
+    }
+
+    void SaiIO::Output(int16_t xL, int16_t xR)
+    {
+        tmp_[tmpIndex_++] = xL; // Left
+        tmp_[tmpIndex_++] = xR; // Right
+    }
+
+    void SaiIO::Pause()
+    {
+        BSP_AUDIO_OUT_SetMute(AUDIO_MUTE_ON);
+        BSP_AUDIO_IN_Pause();
+        BSP_AUDIO_OUT_Pause();
+        ClearBuffer();
+    }
+
+    void SaiIO::Resume()
+    {
+        BSP_AUDIO_IN_Resume();
+        BSP_AUDIO_OUT_Resume();
+        BSP_AUDIO_OUT_SetMute(AUDIO_MUTE_OFF);
+    }
+
+    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)
+    {
+        int audioInVolume = 0;
+        if (inputDevice != 0)
+            audioInVolume = (inputDevice == INPUT_DEVICE_INPUT_LINE_1) ?
+                                60 : 100;
+
+        if (IOBOTH_ == BOTH)
+            if (MyBSP_AUDIO_IN_OUT_Init(inputDevice, OUTPUT_DEVICE_HEADPHONE,
+                                        audioInVolume, FS_) == AUDIO_ERROR)
+                ErrorTrap();
+
+        if (IOBOTH_ == INPUT)
+            if (BSP_AUDIO_IN_Init(inputDevice,
+                                  audioInVolume, FS_) == AUDIO_ERROR)
+                ErrorTrap();
+
+        if (IOBOTH_ == OUTPUT)
+            if (BSP_AUDIO_OUT_Init(OUTPUT_DEVICE_HEADPHONE,
+                                   90, FS_) == AUDIO_ERROR)
+                ErrorTrap();
+
+        if (IOBOTH_ != OUTPUT) InitInput();
+        if (IOBOTH_ != INPUT) InitOutput();
+    }
+
+    void SaiIO::InitInput()
+    {
+        NVIC_SetVector(AUDIO_IN_SAIx_DMAx_IRQ,
+                       (uint32_t)AUDIO_IN_SAIx_DMAx_IRQHandler);
+
+        if (BSP_AUDIO_IN_Record((uint16_t*)inBuffer_,
+                                bufferSize_) == AUDIO_ERROR)
+            ErrorTrap();
+    }
+
+    void SaiIO::InitOutput()
+    {
+        NVIC_SetVector(AUDIO_OUT_SAIx_DMAx_IRQ,
+                       (uint32_t)AUDIO_OUT_SAIx_DMAx_IRQHandler);
+        BSP_AUDIO_OUT_SetAudioFrameSlot(CODEC_AUDIOFRAME_SLOT_02);
+
+        if (BSP_AUDIO_OUT_Play((uint16_t *)outBuffer_,
+                               bufferSize_*AUDIODATA_SIZE) == AUDIO_ERROR)
+            ErrorTrap();
+            
+        // Set output volume of headphone maximum
+        //      AUDIO_IO_Write() is defined in "stm32746g_discovery.c"
+        //      AUDIO_I2C_ADDRESS is defined in "stm32746g_discovery.h"
+        AUDIO_IO_Write(AUDIO_I2C_ADDRESS, 0x1C, 0x17F); // 0x1C: R28 of WM8994
+        AUDIO_IO_Write(AUDIO_I2C_ADDRESS, 0x1D, 0x17F); // 0x1D: R29 of WM8994
+    }
+
+    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;
+    }
+
+    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_;
+
+    int16_t* SaiIO::outBuffer_;
+    int16_t* SaiIO::tmp_;       
+    __IO bool SaiIO::xferred_;
+}
+