First publishment of Shimabara Audio Codec Controller library. Including code for ADAU1361 and UMB-ADAU1361A. Working pretty fine. Checked with LPCXpresso 4337 and Unzen_lpc4337

Dependents:   unzen_sample_LPC4088_quickstart unzen_sample_lpcxpresso_4337_callbacks unzen_sample_nucleo_f746 unzen_delay_sample_nucleo_f746 ... more

shimabaraは、mbedからオーディオ・コーデックのハードウェアを操作するクラス・ライブラリです。このライブラリは雲仙オーディオ・フレームワークと共に使うことを想定して開発しましたが、独立して使うことも可能です。

使い方

shimabaraは BaseAudioCodec, ADAU1361, UMB_ADAU1361Aの三つのクラスを定義しています。いずれのクラスも名前空間simabaraに属しています。実際のアプリケーションで使用するのはshimabara::UMB_ADAU1361Aだけで、このクラスはアクアシグナルのUMB-ADAU1361-Aに対応しています。ヘッダーファイルは umb_adau1361a.hです。

shimabara::UMB_ADAU1361Aのコンストラクタは三つの引数を受け取ります。

  • Fs はサンプル周波数です。これはenum Fs_type型の引数で、やはり名前空間shimabaraに属しています。
  • controller はADAU1361Aが接続されているI2Cポートに対応するI2Cオブジェクトを与えます。shimabaraはこのポートを通してCODECと通信します。
  • Addrには、コーデックのI2Cアドレスを与えます。現時点ではこの引数は0x38固定です。

コンストラクタでオブジェクトを初期化したら、start()メソッドを呼んでください。これでshimabaraはコーデックと通信し、I2Sモードでの動作が始まります。

参考リンク

adau1361.cpp

Committer:
shorie
Date:
2016-05-27
Revision:
4:a838173c951d
Parent:
2:fba0b8afebf0

File content as of revision 4:a838173c951d:

/**
* \file Adau1361.cpp
* \brief implementation of class Adau1361. See Adau1361.h as class definition. 
*/

#include "adau1361.h"
#include <algorithm>

namespace shimabara
{
    
    Adau1361::Adau1361( Fs_Type Fs, I2C & controler, unsigned int Addr  ):
            BaseAudioCodec( Fs )
    {
        i2c = & controler; 
        addr = Addr<<1;     // Justify to right to use mbed library
    }


        // Core clock setting
    static const char init_PLL[][3] =
    {
        {0x40, 0x00, 0x00},    // R0:Clock control
        {0x40, 0x17, 0x00},    // R17, SRC = 1
        {0x40, 0x00, 0x0F}     // R0:Clock Control. Core clock. PLL Start
    };

    
    
    
        // Set non clock registers as default 
    static const char init_Adau1361[][3] =
    {
            // R0,1, are set by init_freq_xxx table
        {0x40, 0x08, 0x00},     // R2: Digital Mic
        {0x40, 0x09, 0x00},     // R3: Rec Power Management
        {0x40, 0x0a, 0x00},     // R4: Rec Mixer Left 0
        {0x40, 0x0b, 0x00},     // R5: Rec Mixer Left 1
        {0x40, 0x0c, 0x00},     // R6: Rec Mixer Right 0
        {0x40, 0x0d, 0x00},     // R7: Rec Mixer Right 1
        {0x40, 0x0e, 0x00},     // R8: Left diff input vol
        {0x40, 0x0f, 0x00},     // R9: Right diff input vol
        {0x40, 0x10, 0x00},     // R10: Rec mic bias
        {0x40, 0x11, 0x00},     // R11: ALC0
        {0x40, 0x12, 0x00},     // R12: ALC1
        {0x40, 0x13, 0x00},     // R13: ALC2
        {0x40, 0x14, 0x00},     // R14: ALC3
        {0x40, 0x15, 0x00},     // R15: Serial Port 0
        {0x40, 0x16, 0x00},     // R16: Serial Port 1
            // R17 is set by init_freq_xxx table
        {0x40, 0x18, 0x00},     // R18: Converter 1
        {0x40, 0x19, 0x10},     // R19:ADC Control. 
        {0x40, 0x1a, 0x00},     // R20: Left digital volume
        {0x40, 0x1b, 0x00},     // R21: Rignt digital volume
        {0x40, 0x1c, 0x00},     // R22: Play Mixer Left 0
        {0x40, 0x1d, 0x00},     // R23: Play Mixer Left 1
        {0x40, 0x1e, 0x00},     // R24: Play Mixer Right 0
        {0x40, 0x1f, 0x00},     // R25: Play Mixer Right 1
        {0x40, 0x20, 0x00},     // R26: Play L/R mixer left
        {0x40, 0x21, 0x00},     // R27: Play L/R mixer right
        {0x40, 0x22, 0x00},     // R28: Play L/R mixer monot
        {0x40, 0x23, 0x02},     // R29: Play HP Left vol
        {0x40, 0x24, 0x02},     // R30: Play HP Right vol
        {0x40, 0x25, 0x02},     // R31: Line output Left vol
        {0x40, 0x26, 0x02},     // R32: Line output Right vol
        {0x40, 0x27, 0x02},     // R33: Play Mono output
        {0x40, 0x28, 0x00},     // R34: Pop surpress
        {0x40, 0x29, 0x00},     // R35: Play Power Management
        {0x40, 0x2a, 0x00},     // R36: DAC Control 0
        {0x40, 0x2b, 0x00},     // R37: DAC Control 1
        {0x40, 0x2c, 0x00},     // R38: DAC control 2
        {0x40, 0x2d, 0xaa},     // R39: Seial port Pad
        {0x40, 0x2f, 0xaa},     // R40: Control Pad 1
        {0x40, 0x30, 0x00},     // R41: Control Pad 2
        {0x40, 0x31, 0x08},     // R42: Jack detect
        {0x40, 0x36, 0x03},     // R67: Dejitter control
    };

    static const char lock_status_address[] = {0x40, 0x07};     // R2 : Byte 5.

    
        // Send single command 
    void Adau1361::send_command( const char table[], int size)
    {
        i2c->write( addr, table, size);
    }


        // Send entire command table
    void Adau1361::send_command_table( const char table[][3], int rows )
    {
        for ( int i=0; i<rows; i++ )  
        {
            send_command(table[i], 3);
        }
    }
    
    
        // loop while the PLL is not locked.
    void Adau1361::wait_pll_lock(void)
    {
        
        do {
            i2c->write( addr, lock_status_address, sizeof(lock_status_address), true);  // send address to read. 
        } while ( !(i2c->read(1) & 0x2) );  // read the PLL status.
    }
    
        
        #define DATA 2  /* data payload of register */
        #define ADDL 1  /* lower address of register */
    void Adau1361::start(void)
    {

            // then, start of configuration as register address order
        send_command_table(init_PLL, sizeof(init_PLL)/3);
        
        
        configure_pll();
        
            // Set all registers.
        send_command_table(init_Adau1361, sizeof(init_Adau1361)/3);    // init Adau1361 as default state.

        configure_board();
            
            // set input gain
        set_line_input_gain( 0, 0 );        // unmute
        set_aux_input_gain( 0, 0, true );   // mute
        set_mic_input_gain( 0, 0, true );    // mute
        set_line_output_gain( 0, 0, true ); // mute
        set_hp_output_gain( 0, 0, true );   // mute
    }
    
#define SET_INPUT_GAIN( x ) ((x<<1)|1)

    void Adau1361::set_line_input_gain(float left_gain, float right_gain, bool mute)
    {
        char data[3];
        int left, right;
        
        
        data[0] = 0x40; // Upper address of register

        if ( mute )
        {
            data[ADDL] = 0x0a; data[DATA] = 0x01; i2c->write( addr, data, 3 );    // R4: mixer 1 enable
            data[ADDL] = 0x0c; data[DATA] = 0x01; i2c->write( addr, data, 3 );    // R6: mixer 2 enable 
        }
        else 
        {
            
                // set left gain
            left = (left_gain+15)/3 ;   // See table 31 LINNG
            left = max( left, 0 );
            left = min( left, 7 );
            data[DATA] = SET_INPUT_GAIN( left );
            
            data[ADDL] = 0x0a; i2c->write( addr, data, 3 );    // R4: mixer 1 enable

                // set right gain
            right = (right_gain+15)/3 ;   // See table 31 LINNG
            right = max( right, 0 );
            right = min( right, 7 );
            data[DATA] = SET_INPUT_GAIN( right );
            
            data[ADDL] = 0x0c; i2c->write( addr, data, 3 );    // R4: mixer 1 enable
            
        }
    }

        
    void Adau1361::set_aux_input_gain(float left_gain, float right_gain, bool mute)
    {
        char data[3];
        int left, right;
        
        
        data[0] = 0x40; // Upper address of register

        if ( mute )
        {
            data[ADDL] = 0x0b; data[DATA] = 0x01; i2c->write( addr, data, 3 );    // R5: mixer 1 L aux mute
            data[ADDL] = 0x0d; data[DATA] = 0x01; i2c->write( addr, data, 3 );    // R7: mixer 2 R aux mute
        }
        else 
        {
            
                // set left gain
            left = (left_gain+15)/3 ;   // See table 31 LINNG
            left = max( left, 0 );
            left = min( left, 7 );
            data[DATA] = left ;
            
            data[ADDL] = 0x0b; i2c->write( addr, data, 3 );    // R5: mixer 1 enable

                // set right gain
            right = (right_gain+15)/3 ;   // See table 31 LINNG
            right = max( right, 0 );
            right = min( right, 7 );
            data[DATA] = right;
            
            data[ADDL] = 0x0d; i2c->write( addr, data, 3 );    // R4: mixer 1 enable
            
        }
    }

        
#define SET_LO_GAIN( x ) ((x<<2)|2)

    void Adau1361::set_line_output_gain(float left_gain, float right_gain, bool mute)
    {
        char data[3];        
        int left, right;
        
        data[0] = 0x40; // Upper address of register
        
        if ( mute )
        {
            data[ADDL] = 0x25; data[DATA] = 0x01; i2c->write( addr, data, 3 );    // R31: LOUTVOL
            data[ADDL] = 0x26; data[DATA] = 0x01; i2c->write( addr, data, 3 );    // R32: LOUTVOL 
        }
        else 
        {
            left = left_gain+57;
            left = max( left, 0 );
            left = min( left, 63 );
                            
            right = right_gain+57;
            right = max( right, 0 );
            right = min( right, 63 );
            
            data[ADDL] = 0x25; data[DATA] = SET_LO_GAIN(left ); i2c->write( addr, data, 3 );    // R31: LOUTVOL
            data[ADDL] = 0x26; data[DATA] = SET_LO_GAIN(right); i2c->write( addr, data, 3 );    // R32: LOUTVOL 

        }
    }

#define SET_HP_GAIN( x ) ((x<<2)|3)

    void Adau1361::set_hp_output_gain(float left_gain, float right_gain, bool mute)
    {
        char data[3];        
        int left, right;
        
        data[0] = 0x40; // Upper address of register
        
        if ( mute )
        {
            data[ADDL] = 0x23; data[DATA] = 0x01; i2c->write( addr, data, 3 );    // R29: LHPVOL
            data[ADDL] = 0x24; data[DATA] = 0x01; i2c->write( addr, data, 3 );    // R30: LHPVOL 
        }
        else 
        {
            left = left_gain+57;
            left = max( left, 0 );
            left = min( left, 63 );
                            
            right = right_gain+57;
            right = max( right, 0 );
            right = min( right, 63 );
            
            data[ADDL] = 0x23; data[DATA] = SET_HP_GAIN(left ); i2c->write( addr, data, 3 );    // R29: LHPVOL
            data[ADDL] = 0x24; data[DATA] = SET_HP_GAIN(right); i2c->write( addr, data, 3 );    // R30: LHPVOL

        }
    }



}