Production Test Program (PTP) for the LPC4088 Experiment Base Board

Dependencies:   EALib I2S LM75B SDFileSystem mbed

TestAudio.cpp

Committer:
embeddedartists
Date:
2014-10-01
Revision:
9:eb6086159020
Parent:
7:48375cb50f3a

File content as of revision 9:eb6086159020:

/*
 *  Copyright 2013 Embedded Artists AB
 *
 *  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.
 */

/******************************************************************************
 * Includes
 *****************************************************************************/
//#define SOUND_8KHZ

#include "mbed.h"
#include "TestAudio.h"
#include "WM8731.h"
#include "I2S.h"
#include "sound.h"

/******************************************************************************
 * Defines and typedefs
 *****************************************************************************/

#define SAMPLERATE 32000

/******************************************************************************
 * Private Functions
 *****************************************************************************/

void TestAudio::echo(void) {
    int to_read = _i2sRx.fifo_points();  //Find out how many stereo samples to read
    
    //Read 'to_read' number of stereo samples.
    _i2sRx.read(_rxBuf, to_read);
    
    //Loop through all stereo samples
    for(int i = 0; i < to_read; i+=2) {
        // Check if wave-file shall be output
        if (_waveIdx > 0)
        {
#if SOUND_8KHZ
            int sample = sound_8k[_waveIdx/4] << 5
            _txBuf[i]             = sample;
            _txBuf[i+1]           = sample;
            _echoBuf[_echoBufPtr] = _rxBuf[i];

            //Increment wave samples pointer and check if all samples have been read, if so, set pointer to zero
            _waveIdx++;
            if (_waveIdx/4 > sound_sz)
            {
                _waveIdx = 0;
            }
#else
            int sample = (unsigned int)sound_32k[_waveIdx] | (((unsigned int)sound_32k[_waveIdx+1]) << 8);
            _txBuf[i]             = sample;
            _txBuf[i+1]           = sample;
            _echoBuf[_echoBufPtr] = _rxBuf[i];

            //Increment wave samples pointer and check if all samples have been read, if so, set pointer to zero
            _waveIdx += 2;
            if (_waveIdx > sound_sz)
            {
                _waveIdx = 0;
            }
#endif
        }
        //Output delayed version of audio input
        else
        {
            //Echo buffer only contains right side samples (since MIC is used as input, which is a mono input)
            //Output is however stereo, so just copy echo bugger to both right and left side for output samples
            _txBuf[i]   = _echoBuf[_echoBufPtr];
            _txBuf[i+1] = _echoBuf[_echoBufPtr];

            //Only fill echo buffer with right side samples, i.e., ignore rxBuf[i+1] content
            _echoBuf[_echoBufPtr]   = _rxBuf[i];
        }

        //Increment echo buffer write pointer and check for wrap-around
        _echoBufPtr++;
        if (_echoBufPtr >= ECHOLENGTH)
        {
            _echoBufPtr = 0;
        }
    }
    
    //Write samples to output/codec
    _i2sTx.write(_txBuf, to_read);
}

/******************************************************************************
 * Public Functions
 *****************************************************************************/

/*
   Prerequisites:
 
   - For this test to work jumpers JP8 and JP9 on the LPC4088 Experiment Base Board
     must both be in positions 1-2
     
   - MIC cable, Line OUT, Headphone...
*/

TestAudio::TestAudio() : _codec(P0_27, P0_28), _i2sTx(I2S_TRANSMIT, p11, p12, p13),
    _i2sRx(I2S_RECEIVE, p14, p33, p34),_aIn(p15),_waveIdx(0),_echoBufPtr(0) {
}

bool TestAudio::runTest() {
    printf("Testing audio... Exit by pressing joystick up\n");
    printf("Joystick down = play short wave-file. Joystick right/left = turn microphone boost on/off\n");

    // joystick used for audio selection    
    DigitalIn up(p32);
    DigitalIn down(p38);
    DigitalIn left(p39);
    DigitalIn right(p37);
    
    for(int i=0; i<ECHOLENGTH; i++)
      _echoBuf[i] = 0;
    
    _codec.power(true);
    _codec.frequency(SAMPLERATE);
    _codec.wordsize(16);  
    _codec.master(true);
    _codec.headphone_volume(0.1);
    _codec.input_select(WM8731_MIC);
    _codec.microphone_boost(true);
    _codec.input_mute(false);
    _codec.output_mute(false);
    _codec.input_power(true);
    _codec.output_power(true);
    _codec.linein_volume(0.7);
    _codec.bypass(true);
    _codec.start();

    _i2sRx.frequency(SAMPLERATE);
    _i2sRx.wordsize(16);
    _i2sRx.stereomono(I2S_STEREO);
    _i2sRx.masterslave(I2S_SLAVE);
    _i2sRx.attach(this, &TestAudio::echo);
    _i2sRx.set_interrupt_fifo_level(1);
    _echoBufPtr = 0;
    _waveIdx = 0;
    _i2sRx.start();

    _i2sTx.frequency(SAMPLERATE);
    _i2sTx.wordsize(16);
    _i2sTx.stereomono(I2S_STEREO);
    _i2sTx.masterslave(I2S_SLAVE);
    _i2sTx.start();

    int lastVol = -1000; // value not important
    do
    {
        //check if joystick-down pressed = play wave-file
        if ((down.read() == 0) && (_waveIdx == 0))
            _waveIdx = 2;

        //check if joystick-left pressed = turn off microphone boost
        if (left.read() == 0)
        {
            _codec.input_mute(true);
            wait(0.2);
            _codec.microphone_boost(false);
            wait(0.2);
            _codec.input_mute(false);
        }

        //check if joystick-right pressed = turn on microphone boost
        if (right.read() == 0)
        {
            _codec.input_mute(true);
            wait(0.2);
            _codec.microphone_boost(true);
            wait(0.2);
            _codec.input_mute(false);
        }

        //attempt to filter out the small variations in analog values and
        //only update volume when a "large enough" change is detected.
        float v = _aIn;
        int val = ((int)(v*1000))>>2;
        if (val != lastVol) {
            _codec.headphone_volume(v);
            lastVol = val;
        }
        //_codec.headphone_volume(_aIn);
        wait(0.25);
    } while (up.read() != 0);

    _codec.power(false);
    return true;
}