# PM_SetAmpGainLevel*

## 構文

      #include <twl/spi.h>

      u32 PM_SetAmpGainLevel( u8 level );

      u32 PM_SetAmpGainLevelAsync( u8 level, PMCallback callback, void* arg );

## 引数

level | アンプのゲインを決定する設定値
callback | コマンドが終了したときに呼ばれるコールバック
arg | コールバックを呼ぶ際の引数

## 返り値

PM_RESULT_SUCCESS ならば、コマンドの実行が成功した(同期関数の場合)か、コマンドをARM7に送信することに成功した(非同期関数の場合)ことを表します。

PM_RESULT_BUSY ならば、 SPI が他の処理に占有されており処理できなかったことを示します。

## 説明

プログラマブルゲインアンプのゲインを設定します。
この関数は動作モードが TWL モードのときのみ使用することが出来ます。

level は `u8` 型の値で、0 〜 119 のいずれかを指定してください。

`PM_SetAmpGain*()` と `PM_SetAmpGainLevel*()` の違い

設定関数は `PM_SetAmpGain*()` と `PM_SetAmpGainLevel*()` の２種類 が存在します。前者は旧 DS から存在している関数で、ゲインを 4段階で指定するものです。後者はこのリファレンスページで説明している TWL で新設された関数で、ゲインを 120 段階で指定することができます。

4段階で指定する `PM_SetAmpGain*()` はどのモードでも使用することが出来ます。指定された値はいつでもその通りに設定されます。

120 段階で指定する `PM_SetAmpGainLevel*()` は TWL HYBRID か TWL LIMITED のときにしか使用することが出来ません。そして実際に指定した 120 段階で設定されるかどうかは、CODEC のモードによります。CODEC が TWL モードで動作している場合　(この場合の動作モードは必ず TWL モードのはずです。) は、120段階の指定がそのまま 120 段階の設定になります。しかしそれ以外の場合は、120 段階で設定しても、その値が 4段階に均されて設定されます。この 4 段階は、`PM_SetAmpGain*()` で設定される 4 段階を踏襲しています。

level の値と設定されるゲイン

引数 level の値と、実際に設定される アンプゲインは以下のようになります。

> CODEC が TWLモードの場合

> level | 設定されるゲイン
> --- | ---
> 0 | 10.5dB
> 1 | 11.0dB
> 2 | 11.5dB
> ： | ：
> n | 10.5 + ( n x 0.5 ) dB
> ： | ：
> 119 | 70.0dB

> CODEC が DS モードの場合

> level | 設定されるゲイン
> --- | ---
> 0 〜 36 | 26.0 dB (120段階表記の 31 に相当)
> 37 〜 48 | 32.0 dB (120段階表記の 43 に相当)
> 49 〜 60 | 38.0 dB (120段階表記の 55 に相当)
> 61 〜 119 | 44.0 dB (120段階表記の 67 に相当)

非同期関数について

この関数はARM7に該当動作を行うコマンドをPXIで送り、それを受け取ったARM7側がPMICを操作することで実行されます。従って関数を呼び出して即時に動作されるわけではありません。動作の終了まで待つ同期型の関数と、コマンドをARM7に送るだけの非同期型の関数が用意されていますので動作目的に合わせて使用してください。(関数名にAsync がついているものが非同期関数です。)

非同期関数を呼び出した場合、ARM7側での処理が終了したときに指定のコールバック callback が呼び出されます。コールバックの型 `PMCallback` は

> `typedef void ( *PMCallback )( u32 result, void* arg );`

で定義されます。このコールバックは PXI 割り込みハンドラの中から呼び出されます。

コールバックの引数は、第一引数 result がコマンドの結果を表します。これは `PM_RESULT_SUCCESS` または `PM_RESULT_BUSY` となります。第二引数は arg を返します。

PM_RESULT_BUSY について

SPI はPM以外にも様々な処理で使用されています。そのようなときに本関数を呼び出すと、ARM7 までコマンドを送り、そこで BUSY という判定が行われ、処理は行われずに ARM9 へ `PM_RESULT_BUSY` が通知されます。また他の PM 処理を行っている最中に本関数を呼び出すと、ARM9 側でそれを判断し `PM_RESULT_BUSY` を返します。(この場合は ARM7 への通知を行う前に判断します。)

従って、確実に本関数を成功させようとすれば、次のように成功するまでループするようにしてください。(引数が間違っているというようなミスは考慮していません。)

> (例)
> `while( PM_SetAmpGainLevel( ... ) != PM_RESULT_SUCCESS )
> {
> }`

Async 関数を用いる場合は例えば以下のように記述できます。

> (例)`
> void setResult( u32 result, void* arg )
> {
> if ( arg )
> {
> *(u32*)arg = result;
> }
> }
> while(1)
> {
> volatile u32 result = PM_RESULT_NONE; //結果としては返らない値
> while ( PM_SetAmpGainLevelAsync(..., setResult, (void*)&result ) != PM_RESULT_SUCCESS )
> {
> }
> // 別の処理など
> otherProcess();
> // 処理終了待ち
> while( result == PM_RESULT_NONE )
> {
> }
> // 成功したならループから抜ける
> if ( result == PM_RESULT_SUCCESS )
> {
> break;
> }
> }`

## 内部動作

NITRO ハードウェアでは、PMIC のレジスタ PGA_GAIN を操作しています。 TWL ハードウェアでは CODEC を操作します。

## 参照

`PM_Init, PM_SetAmp*, PM_SetAmpGain*, PM_GetAmpGainLevel
`

## 履歴

2009/06/03 `PM_Init()` についての記述を削除 (`OS_Init()` が必須となったため)
2008/05/01 初版。`PM_SetAmpGain*()` から分岐