ボリューム制御

EZ-KIT LiteのSW2, SW3を使ってボリュームのアップダウンをしてみました。PF割り込みを使っています。ボリュームの変更はAC97のヘッドホン出力ゲインの変更で行っています。ゲインは31ステップなので、中間の15を初期値としています。

このプログラムの中で一番注意しなければならないのは、PFHandler()の中で呼んでいるfwEzZKit2191のiAC97Writeメンバー関数です。これはAC97にコマンドを送る関数ですが、同様の関数がmain()の中では"t"で始まる関数であるのに対して、こちらは"i"で始まっています。t, iはそれぞれtask、interruptコンテキストで使用されることを意味しています。MCMはこの点を厳しく区別しますので注意してください。

なお、割り込みの取り扱いについては割り込みを使おうPF割り込みを使おうを参照してください。また、下のサンプルはプログラムの前半を省略しています。トークスルーを参考に前半を作ってみてください。答えがわからない人向けにプロジェクトをダウンロードできるようにしておきます。

//**************************************************************************
//
//  メイン関数
//
//  メイン関数では次のことを行う
//
//  1. 割り込みハンドラ登録
//  2. フレームワークのインスタンス生成
//  3. フレームワークの実行
//  4. コーデックの初期化が終わるのを待つ
//  5. コーデックのミュート解除
//  6. 無限ループ
//
//  以上の処理はほとんどのプログラムで共通である
//
//**************************************************************************

int main (void)
{
   
    interrupt( SIG_INT5 ,&sportHandler);  // SPORT割り込みハンドラ登録
    interrupt( SIG_INT15, &PFHandler );   // PF割り込みハンドラ登録
    enable_interrupts();                  // グローバル割り込みイネーブル
    
    setupPF();
                                                
    myVol = new CVolume( );               // インスタンス生成
    myVol->run();                         // AC97制御開始

                                          // 入出力のミュートを解除
    myVol->tAC97Write( ac97::HEAD_VOLUME, ac97::gain( false, volume, volume )  ); 
    myVol->tAC97Write( ac97::RECORD_GAIN, ac97::gain( false, 8, 8 ) );
        
                                          // メインルーチンではあとは割り込み待ち
    while( 1 )
         asm( "idle;" );
}

//**************************************************************************
//
//  SPORT割り込みハンドラ
//  単にインスタンスに制御を渡すだけ
//
//**************************************************************************
void sportHandler( int intr )
{
        myVol->handleInterrupt();       
}

//**************************************************************************
//
//  PFの設定
//  0-3はLED出力, 4-5は押しボタン入力
//
//**************************************************************************

void setupPF(void)
{
    sysreg_write( sysreg_IOPG, General_Purpose_IO );
    io_space_write( DIR,    0x0f ); // set PF0-3 to output
    io_space_write( FSPR,   0x00 ); // Source polarity is positive.
    io_space_write( FSSR,   0x30 ); // set PF4,5 to edge sense.
    io_space_write( FSBER,  0x00 ); // set PF4,5 to one edge.
    io_space_write( MASKAS, 0x30 ); // set PF4,5 to PF interrupt A
    io_space_write( FLAGS, 0xf & ~volume );   // set singal to LED
    io_space_write( FLAGC, 0xf & volume );  // clear the 0 LED.
}

//**************************************************************************
//
//  PF割り込みハンドラ
//  ボリュームのアップダウンとLED点灯
//
//**************************************************************************
#define MAX( a, b ) ( a > b ? a : b )
#define MIN( a, b ) ( a < b ? a : b )

void PFHandler( int sig )
{
    sysreg_write( sysreg_IOPG, General_Purpose_IO );
    if ( io_space_read( FLAGS ) & 0x10 )            // PF4 を押したとき 

    {
        io_space_write( FLAGC, 0x10 );  // 割り込みクリア
        volume = MAX( volume-1, 0 );    // ボリュームダウン
    }
        
        
    if ( io_space_read( FLAGS ) & 0x20 )            // PF5 を押したとき 
    {
        io_space_write( FLAGC, 0x20 );  // 割り込みクリア
        volume = MIN( volume+1, 31 );    // ボリュームアップ
    }
        
        
                                  // ここでヘッドホン出力を設定
                                  // メンバー関数の名前に注意
    myVol->iAC97Write( ac97::HEAD_VOLUME, ac97::gain( false, volume, volume )  ); 
        
                                 // LED設定
    io_space_write( FLAGS, 0xf & ~volume );   // set singal to LED
    io_space_write( FLAGC, 0xf & volume );  // clear the 0 LED.
}

プログラムを走らせてSW2, SW3を押すと、ボリュームのアップダウンにあわせてLEDの表示が変わります。

⇒次はレベルメーター

2191空挺団 | プログラム | EZ-KIT | こぼれ話 | アーキテクチャー | 命令 | レジスタ | DSP掲示板 | FAQ |